</p>
<ol>
+<li> Changed: GridTools, DoFTools, MGTools and VectorTools are now namespaces. They have long
+been classes that had only public, static member functions, making
+the end result semantically exactly equivalent to a namespace, which is
+also how it was used. This is now also reflected in the actual code.
+<br>
+(Wolfgang Bangerth, 2011/04/27, 2011/09/14)
+
<li> Changed: The PETScWrapper::VectorBase and PETScWrapper::MatrixBase
classes tried to keep track of
whether the last operation done on a vector was to add to an element or to
<br>
(Habib Talavatifard, Wolfgang Bangerth 2011/05/09, 2011/05/27)
-<li> Changed: DoFTools is now a namespace. It has long been a class that
-had only public, static member functions, making the end result semantically
-exactly equivalent to a namespace, which is also how it was used. This is
-now also reflected in the actual code.
-<br>
-(Wolfgang Bangerth, 2011/04/27)
-
<li> New: The version of DoFTools::make_flux_sparsity_pattern that takes
the coupling masks is now also available for hp::DoFHandler objects.
<br>
/**
- * This class is a collection of algorithms working on triangulations,
+ * This namespace is a collection of algorithms working on triangulations,
* such as shifting or rotating triangulations, but also finding a
* cell that contains a given point. See the descriptions of the
* individual functions for more information.
*
* @ingroup grid
*/
-class GridTools
+namespace GridTools
{
- public:
- /**
- * Return the diameter of a
- * triangulation. The diameter is
- * computed using only the
- * vertices, i.e. if the diameter
- * should be larger than the
- * maximal distance between
- * boundary vertices due to a
- * higher order mapping, then
- * this function will not catch
- * this.
- */
- template <int dim, int spacedim>
- static
- double diameter (const Triangulation<dim, spacedim> &tria);
-
- /**
- * Compute the volume (i.e. the dim-dimensional measure) of the
- * triangulation. We compute the measure using the integral
- * $\int 1 \; dx$. The integral approximated is approximated
- * via quadrature for which we need the mapping argument.
- *
- * This function also works for objects of type
- * parallel::distributed::Triangulation, in which case the
- * function is a collective operation.
- */
- template <int dim, int spacedim>
- static
- double volume (const Triangulation<dim,spacedim> &tria,
- const Mapping<dim,spacedim> &mapping = (StaticMappingQ1<dim,spacedim>::mapping));
-
- /**
- * Given a list of vertices (typically
- * obtained using
- * Triangulation::get_vertices) as the
- * first, and a list of vertex indices
- * that characterize a single cell as the
- * second argument, return the measure
- * (area, volume) of this cell. If this
- * is a real cell, then you can get the
- * same result using
- * <code>cell-@>measure()</code>, but
- * this function also works for cells
- * that do not exist except that you make
- * it up by naming its vertices from the
- * list.
- */
- template <int dim>
- static
- double cell_measure (const std::vector<Point<dim> > &all_vertices,
- const unsigned int (&vertex_indices)[GeometryInfo<dim>::vertices_per_cell]);
-
- /**
- * Remove vertices that are not
- * referenced by any of the
- * cells. This function is called
- * by all <tt>GridIn::read_*</tt>
- * functions to eliminate
- * vertices that are listed in
- * the input files but are not
- * used by the cells in the input
- * file. While these vertices
- * should not be in the input
- * from the beginning, they
- * sometimes are, most often when
- * some cells have been removed
- * by hand without wanting to
- * update the vertex lists, as
- * they might be lengthy.
- *
- * This function is called by all
- * <tt>GridIn::read_*</tt>
- * functions as the triangulation
- * class requires them to be
- * called with used vertices
- * only. This is so, since the
- * vertices are copied verbatim
- * by that class, so we have to
- * eliminate unused vertices
- * beforehand.
- *
- * Not implemented for the
- * codimension one case.
- */
- template <int dim, int spacedim>
- static
- void delete_unused_vertices (std::vector<Point<spacedim> > &vertices,
- std::vector<CellData<dim> > &cells,
- SubCellData &subcelldata);
-
- /**
- * Remove vertices that are duplicated,
- * due to the input of a structured grid,
- * for example. If these vertices are not
- * removed, the faces bounded by these
- * vertices become part of the boundary,
- * even if they are in the interior of
- * the mesh.
- *
- * This function is called by some
- * <tt>GridIn::read_*</tt> functions. Only
- * the vertices with indices in @p
- * considered_vertices are tested for
- * equality. This speeds up the algorithm,
- * which is quadratic and thus quite slow
- * to begin with. However, if you wish to
- * consider all vertices, simply pass an
- * empty vector.
- *
- * Two vertices are considered equal if
- * their difference in each coordinate
- * direction is less than @p tol.
- */
- template <int dim, int spacedim>
- static
- void delete_duplicated_vertices (std::vector<Point<spacedim> > &all_vertices,
- std::vector<CellData<dim> > &cells,
- SubCellData &subcelldata,
- std::vector<unsigned int> &considered_vertices,
- const double tol=1e-12);
-
- /**
- * Transform the vertices of the given
- * triangulation by applying the
- * predicate to all its vertices. Since
- * the internal consistency of a
- * triangulation can only be guaranteed
- * if the transformation is applied to
- * the vertices of only one level of a
- * hierarchically refined cells, this
- * function may only be used if all cells
- * of the triangulation are on the same
- * refinement level.
- *
- * The predicate given as
- * argument is used to transform
- * each vertex. Its respective
- * type has to offer a
- * function-like syntax, i.e. the
- * predicate is either an object
- * of a type that has an
- * <tt>operator()</tt>, or it is a
- * pointer to the function. In
- * either case, argument and
- * return value have to be of
- * type <tt>Point<dim></tt>.
- *
- * This function is used in the
- * "Possibilities for extensions" section
- * of step-38.
- */
- template <int dim, typename Predicate, int spacedim>
- static
- void transform (const Predicate &predicate,
- Triangulation<dim,spacedim> &triangulation);
-
- /**
- * Shift each vertex of the
- * triangulation by the given
- * shift vector. This function
- * uses the transform()
- * function above, so the
- * requirements on the
- * triangulation stated there
- * hold for this function as
- * well.
- */
- template <int dim, int spacedim>
- static
- void shift (const Point<spacedim> &shift_vector,
- Triangulation<dim,spacedim> &triangulation);
-
-
- /**
- * Rotate all vertices of the
- * given two-dimensional
- * triangulation in
- * counter-clockwise sense around
- * the origin of the coordinate
- * system by the given angle
- * (given in radians, rather than
- * degrees). This function uses
- * the transform() function
- * above, so the requirements on
- * the triangulation stated there
- * hold for this function as
- * well.
- */
- static
- void rotate (const double angle,
- Triangulation<2> &triangulation);
-
- /**
- * Scale the entire triangulation
- * by the given factor. To
- * preserve the orientation of
- * the triangulation, the factor
- * must be positive.
- *
- * This function uses the
- * transform() function
- * above, so the requirements on
- * the triangulation stated there
- * hold for this function as
- * well.
- */
- template <int dim, int spacedim>
- static
- void scale (const double scaling_factor,
- Triangulation<dim, spacedim> &triangulation);
-
- /**
- * Find and return the number of
- * the used vertex in a given
- * Container that is located closest
- * to a given point @p p. The
- * type of the first parameter
- * may be either Triangulation,
- * DoFHandler, hp::DoFHandler, or
- * MGDoFHandler.
- *
- * @author Ralf B. Schulz, 2006
- */
- template <int dim, template <int, int> class Container, int spacedim>
- static
- unsigned int
- find_closest_vertex (const Container<dim, spacedim> &container,
- const Point<spacedim> &p);
-
- /**
- * Find and return a vector of
- * iterators to active cells that
- * surround a given vertex @p vertex.
- * The type of the first parameter
- * may be either Triangulation,
- * DoFHandler, hp::DoFHandler, or
- * MGDoFHandler.
- *
- * For locally refined grids, the
- * vertex itself might not be a vertex
- * of all adjacent cells, but will
- * always be located on a face or an
- * edge of the adjacent cells returned.
- *
- * @author Ralf B. Schulz,
- * Wolfgang Bangerth, 2006
- */
- template<int dim, template <int, int> class Container, int spacedim>
- static
- std::vector<typename Container<dim,spacedim>::active_cell_iterator>
- find_cells_adjacent_to_vertex (const Container<dim,spacedim> &container,
- const unsigned int vertex);
-
-
- /**
- * Find and return an iterator to
- * the active cell that surrounds
- * a given point @p ref. The
- * type of the first parameter
- * may be either
- * Triangulation,
- * DoFHandler, or
- * MGDoFHandler, i.e. we
- * can find the cell around a
- * point for iterators into each
- * of these classes.
- *
- * This is solely a wrapper function
- * for the @p interpolate function
- * given below,
- * providing backward compatibility.
- * A Q1 mapping is used for the
- * boundary, and the iterator to
- * the cell in which the point
- * resides is returned.
- *
- * It is recommended to use the
- * other version of this function,
- * as it simultaneously delivers the
- * local coordinate of the given point
- * without additional computational cost.
- */
- template <int dim, template <int,int> class Container, int spacedim>
- static
- typename Container<dim,spacedim>::active_cell_iterator
- find_active_cell_around_point (const Container<dim,spacedim> &container,
- const Point<spacedim> &p);
-
- /**
- * Find and return an iterator to
- * the active cell that surrounds
- * a given point @p p. The
- * type of the first parameter
- * may be either
- * Triangulation,
- * DoFHandler, hp::DoFHandler, or
- * MGDoFHandler, i.e., we
- * can find the cell around a
- * point for iterators into each
- * of these classes.
- *
- * The algorithm used in this
- * function proceeds by first
- * looking for vertex located
- * closest to the given point, see
- * find_closest_vertex(). Secondly,
- * all adjacent cells to this point
- * are found in the mesh, see
- * find_cells_adjacent_to_vertex().
- * Lastly, for each of these cells,
- * it is tested whether the point is
- * inside. This check is performed
- * using arbitrary boundary mappings.
- * Still, it is possible that due
- * to roundoff errors, the point
- * cannot be located exactly inside
- * the unit cell. In this case,
- * even points at a very small
- * distance outside the unit cell
- * are allowed.
- *
- * If a point lies on the
- * boundary of two or more cells,
- * then the algorithm tries to identify
- * the cell that is of highest
- * refinement level.
- *
- * The function returns an
- * iterator to the cell, as well
- * as the local position of the
- * point inside the unit
- * cell. This local position
- * might be located slightly
- * outside an actual unit cell,
- * due to numerical roundoff.
- * Therefore, the point returned
- * by this function should
- * be projected onto the unit cell,
- * using GeometryInfo::project_to_unit_cell.
- * This is not automatically performed
- * by the algorithm.
- */
- template <int dim, template<int, int> class Container, int spacedim>
- static
- std::pair<typename Container<dim,spacedim>::active_cell_iterator, Point<spacedim> >
- find_active_cell_around_point (const Mapping<dim,spacedim> &mapping,
- const Container<dim,spacedim> &container,
- const Point<spacedim> &p);
-
- /**
- * A version of the previous function
- * where we use that mapping on a given
- * cell that corresponds to the active
- * finite element index of that
- * cell. This is obviously only useful
- * for hp problems, since the active
- * finite element index for all other DoF
- * handlers is always zero.
- */
- template <int dim, int spacedim>
- static
- std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
- find_active_cell_around_point (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &container,
- const Point<spacedim> &p);
-
- /**
- * Return a list of all descendents of
- * the given cell that are active. For
- * example, if the current cell is once
- * refined but none of its children are
- * any further refined, then the returned
- * list will contain all its children.
- *
- * If the current cell is already active,
- * then the returned list is empty
- * (because the cell has no children that
- * may be active).
- *
- * Since in C++ the type of the Container
- * template argument (which can be
- * Triangulation, DoFHandler,
- * MGDoFHandler, or hp::DoFHandler) can
- * not be deduced from a function call,
- * you will have to specify it after the
- * function name, as for example in
- * <code>GridTools::get_active_child_cells@<DoFHandler@<dim@>
- * @> (cell)</code>.
- */
- template <class Container>
- static
- std::vector<typename Container::active_cell_iterator>
- get_active_child_cells (const typename Container::cell_iterator &cell);
-
- /**
- * Extract the active cells around a given
- * cell @p cell and return them in the
- * vector @p active_neighbors.
- */
- template <class Container>
- static void
- get_active_neighbors (const typename Container::active_cell_iterator &cell,
- std::vector<typename Container::active_cell_iterator> &active_neighbors);
-
- /**
- * Produce a sparsity pattern in which
- * nonzero entries indicate that two
- * cells are connected via a common
- * face. The diagonal entries of the
- * sparsity pattern are also set.
- *
- * The rows and columns refer to the
- * cells as they are traversed in their
- * natural order using cell iterators.
- */
- template <int dim, int spacedim>
- static void
- get_face_connectivity_of_cells (const Triangulation<dim, spacedim> &triangulation,
- SparsityPattern &connectivity);
-
- /**
- * Use the METIS partitioner to generate
- * a partitioning of the active cells
- * making up the entire domain. After
- * calling this function, the subdomain
- * ids of all active cells will have
- * values between zero and
- * @p n_partitions-1. You can access the
- * subdomain id of a cell by using
- * <tt>cell-@>subdomain_id()</tt>.
- *
- * This function will generate an error
- * if METIS is not installed unless
- * @p n_partitions is one. I.e., you can
- * write a program so that it runs in the
- * single-processor single-partition case
- * without METIS installed, and only
- * requires METIS when multiple
- * partitions are required.
- */
- template <int dim, int spacedim>
- static
- void
- partition_triangulation (const unsigned int n_partitions,
- Triangulation<dim, spacedim> &triangulation);
-
- /**
- * This function does the same as the
- * previous one, i.e. it partitions a
- * triangulation using METIS into a
- * number of subdomains identified by the
- * <code>cell-@>subdomain_id()</code>
- * flag.
- *
- * The difference to the previous
- * function is the second argument, a
- * sparsity pattern that represents the
- * connectivity pattern between cells.
- *
- * While the function above builds it
- * directly from the triangulation by
- * considering which cells neighbor each
- * other, this function can take a more
- * refined connectivity graph. The
- * sparsity pattern needs to be of size
- * $N\times N$, where $N$ is the number
- * of active cells in the
- * triangulation. If the sparsity pattern
- * contains an entry at position $(i,j)$,
- * then this means that cells $i$ and $j$
- * (in the order in which they are
- * traversed by active cell iterators)
- * are to be considered connected; METIS
- * will then try to partition the domain
- * in such a way that (i) the subdomains
- * are of roughly equal size, and (ii) a
- * minimal number of connections are
- * broken.
- *
- * This function is mainly useful in
- * cases where connections between cells
- * exist that are not present in the
- * triangulation alone (otherwise the
- * previous function would be the simpler
- * one to use). Such connections may
- * include that certain parts of the
- * boundary of a domain are coupled
- * through symmetric boundary conditions
- * or integrals (e.g. friction contact
- * between the two sides of a crack in
- * the domain), or if a numerical scheme
- * is used that not only connects
- * immediate neighbors but a larger
- * neighborhood of cells (e.g. when
- * solving integral equations).
- *
- * In addition, this function may be
- * useful in cases where the default
- * sparsity pattern is not entirely
- * sufficient. This can happen because
- * the default is to just consider face
- * neighbors, not neighboring cells that
- * are connected by edges or
- * vertices. While the latter couple when
- * using continuous finite elements, they
- * are typically still closely connected
- * in the neighborship graph, and METIS
- * will not usually cut important
- * connections in this case. However, if
- * there are vertices in the mesh where
- * many cells (many more than the common
- * 4 or 6 in 2d and 3d, respectively)
- * come together, then there will be a
- * significant number of cells that are
- * connected across a vertex, but several
- * degrees removed in the connectivity
- * graph built only using face
- * neighbors. In a case like this, METIS
- * may sometimes make bad decisions and
- * you may want to build your own
- * connectivity graph.
- */
- template <int dim, int spacedim>
- static
- void
- partition_triangulation (const unsigned int n_partitions,
- const SparsityPattern &cell_connection_graph,
- Triangulation<dim,spacedim> &triangulation);
-
- /**
- * For each active cell, return in the
- * output array to which subdomain (as
- * given by the <tt>cell->subdomain_id()</tt>
- * function) it belongs. The output array
- * is supposed to have the right size
- * already when calling this function.
- *
- * This function returns the association
- * of each cell with one subdomain. If
- * you are looking for the association of
- * each @em DoF with a subdomain, use the
- * <tt>DoFTools::get_subdomain_association</tt>
- * function.
- */
- template <int dim, int spacedim>
- static void
- get_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
- std::vector<types::subdomain_id_t> &subdomain);
-
- /**
- * Count how many cells are uniquely
- * associated with the given @p subdomain
- * index.
- *
- * This function may return zero
- * if there are no cells with the
- * given @p subdomain index. This
- * can happen, for example, if
- * you try to partition a coarse
- * mesh into more partitions (one
- * for each processor) than there
- * are cells in the mesh.
- *
- * This function returns the number of
- * cells associated with one
- * subdomain. If you are looking for the
- * association of @em DoFs with this
- * subdomain, use the
- * <tt>DoFTools::count_dofs_with_subdomain_association</tt>
- * function.
- */
- template <int dim, int spacedim>
- static unsigned int
- count_cells_with_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
- const types::subdomain_id_t subdomain);
-
- /**
- * Given two mesh containers
- * (i.e. objects of type
- * Triangulation, DoFHandler,
- * hp::DoFHandler, or
- * MGDoFHandler) that are based
- * on the same coarse mesh, this
- * function figures out a set of
- * cells that are matched between
- * the two meshes and where at
- * most one of the meshes is more
- * refined on this cell. In other
- * words, it finds the smallest
- * cells that are common to both
- * meshes, and that together
- * completely cover the domain.
- *
- * This function is useful, for
- * example, in time-dependent or
- * nonlinear application, where
- * one has to integrate a
- * solution defined on one mesh
- * (e.g., the one from the
- * previous time step or
- * nonlinear iteration) against
- * the shape functions of another
- * mesh (the next time step, the
- * next nonlinear iteration). If,
- * for example, the new mesh is
- * finer, then one has to obtain
- * the solution on the coarse
- * mesh (mesh_1) and interpolate
- * it to the children of the
- * corresponding cell of
- * mesh_2. Conversely, if the new
- * mesh is coarser, one has to
- * express the coarse cell shape
- * function by a linear
- * combination of fine cell shape
- * functions. In either case, one
- * needs to loop over the finest
- * cells that are common to both
- * triangulations. This function
- * returns a list of pairs of
- * matching iterators to cells in
- * the two meshes that can be
- * used to this end.
- *
- * Note that the list of these
- * iterators is not necessarily
- * order, and does also not
- * necessarily coincide with the
- * order in which cells are
- * traversed in one, or both, of
- * the meshes given as arguments.
- */
- template <typename Container>
- static
- std::list<std::pair<typename Container::cell_iterator,
- typename Container::cell_iterator> >
- get_finest_common_cells (const Container &mesh_1,
- const Container &mesh_2);
-
- /**
- * Return true if the two
- * triangulations are based on
- * the same coarse mesh. This is
- * determined by checking whether
- * they have the same number of
- * cells on the coarsest level,
- * and then checking that they
- * have the same vertices.
- *
- * The two meshes may have
- * different refinement histories
- * beyond the coarse mesh.
- */
- template <int dim, int spacedim>
- static
- bool
- have_same_coarse_mesh (const Triangulation<dim, spacedim> &mesh_1,
- const Triangulation<dim, spacedim> &mesh_2);
-
- /**
- * The same function as above,
- * but working on arguments of
- * type DoFHandler,
- * hp::DoFHandler, or
- * MGDoFHandler. This function is
- * provided to allow calling
- * have_same_coarse_mesh for all
- * types of containers
- * representing triangulations or
- * the classes built on
- * triangulations.
- */
- template <typename Container>
- static
- bool
- have_same_coarse_mesh (const Container &mesh_1,
- const Container &mesh_2);
-
- /**
- * Return the diamater of the smallest
- * active cell of a triangulation. See
- * step-24 for an example
- * of use of this function.
- */
- template <int dim, int spacedim>
- static
- double
- minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
-
- /**
- * Return the diamater of the largest
- * active cell of a triangulation.
- */
- template <int dim, int spacedim>
- static
- double
- maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
-
- /**
- * Given the two triangulations
- * specified as the first two
- * arguments, create the
- * triangulation that contains
- * the finest cells of both
- * triangulation and store it in
- * the third parameter. Previous
- * content of @p result will be
- * deleted.
- *
- * @note This function is intended
- * to create an adaptively refined
- * triangulation that contains the
- * <i>most refined cells</i> from
- * two input triangulations that
- * were derived from the <i>same </i>
- * coarse grid by adaptive refinement.
- * This is an operation sometimes
- * needed when one solves for two
- * variables of a coupled problem
- * on separately refined meshes on
- * the same domain (for example
- * because these variables have
- * boundary layers in different places)
- * but then needs to compute something
- * that involves both variables or
- * wants to output the result into a
- * single file. In both cases, in
- * order not to lose information,
- * the two solutions can not be
- * interpolated onto the respectively
- * other mesh because that may be
- * coarser than the ones on which
- * the variable was computed. Rather,
- * one needs to have a mesh for the
- * domain that is at least as fine
- * as each of the two initial meshes.
- * This function computes such a mesh.
- *
- * @note If you want to create
- * a mesh that is the merger of
- * two other coarse meshes, for
- * example in order to compose a mesh
- * for a complicated geometry from
- * meshes for simpler geometries,
- * take a look at
- * GridGenerator::merge_triangulations .
- */
- template <int dim, int spacedim>
- static
- void
- create_union_triangulation (const Triangulation<dim, spacedim> &triangulation_1,
- const Triangulation<dim, spacedim> &triangulation_2,
- Triangulation<dim, spacedim> &result);
-
- /**
- * Given a triangulation and a
- * list of cells whose children
- * have become distorted as a
- * result of mesh refinement, try
- * to fix these cells up by
- * moving the center node around.
- *
- * The function returns a list of
- * cells with distorted children
- * that couldn't be fixed up for
- * whatever reason. The returned
- * list is therefore a subset of
- * the input argument.
- *
- * For a definition of the
- * concept of distorted cells,
- * see the
- * @ref GlossDistorted "glossary entry".
- * The first argument passed to the
- * current function is typically
- * the exception thrown by the
- * Triangulation::execute_coarsening_and_refinement
- * function.
- */
- template <int dim, int spacedim>
- static
- typename Triangulation<dim,spacedim>::DistortedCellList
- fix_up_distorted_child_cells (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
- Triangulation<dim,spacedim> &triangulation);
-
- /**
- * This function implements a boundary
- * subgrid extraction. Given a
- * <dim,spacedim>-Triangulation (the
- * "volume mesh") the function extracts a
- * subset of its boundary (the "surface
- * mesh"). The boundary to be extracted
- * is specified by a list of
- * boundary_ids. If none is specified
- * the whole boundary will be
- * extracted. The function is used in
- * step-38.
- *
- * It also builds a mapping linking the
- * cells on the surface mesh to the
- * corresponding faces on the volume
- * one. This mapping is the return value
- * of the function.
- *
- * @note The function builds the surface
- * mesh by creating a coarse mesh from
- * the selected faces of the coarse cells
- * of the volume mesh. It copies the
- * boundary indicators of these faces to
- * the cells of the coarse surface
- * mesh. The surface mesh is then refined
- * in the same way as the faces of the
- * volume mesh are. In order to ensure
- * that the surface mesh has the same
- * vertices as the volume mesh, it is
- * therefore important that you assign
- * appropriate boundary objects through
- * Triangulation::set_boundary to the
- * surface mesh object before calling
- * this function. If you don't, the
- * refinement will happen under the
- * assumption that all faces are straight
- * (i.e using the StraightBoundary class)
- * rather than any curved boundary object
- * you may want to use to determine the
- * location of new vertices.
- *
- * @note Oftentimes, the
- * <code>Container</code>
- * template type will be of kind
- * Triangulation; in that case,
- * the map that is returned will
- * be between Triangulation cell
- * iterators of the surface mesh
- * and Triangulation face
- * iterators of the volume
- * mesh. However, one often needs
- * to have this mapping between
- * DoFHandler (or hp::DoFHandler)
- * iterators. In that case, you
- * can pass DoFHandler arguments
- * as first and second parameter;
- * the function will in that case
- * re-build the triangulation
- * underlying the second argument
- * and return a map between
- * DoFHandler iterators. However,
- * the function will not actually
- * distribute degrees of freedom
- * on this newly created surface
- * mesh.
- *
- * @note The algorithm outlined
- * above assumes that all faces
- * on higher refinement levels
- * always have exactly the same
- * boundary indicator as their
- * parent face. Consequently, we
- * can start with coarse level
- * faces and build the surface
- * mesh based on that. It would
- * not be very difficult to
- * extend the function to also
- * copy boundary indicators from
- * finer level faces to their
- * corresponding surface mesh
- * cells, for example to
- * accomodate different geometry
- * descriptions in the case of
- * curved boundaries.
- */
- template <template <int,int> class Container, int dim, int spacedim>
- static
- std::map<typename Container<dim-1,spacedim>::cell_iterator,
- typename Container<dim,spacedim>::face_iterator>
- extract_boundary_mesh (const Container<dim,spacedim> &volume_mesh,
- Container<dim-1,spacedim> &surface_mesh,
- const std::set<unsigned char> &boundary_ids
- = std::set<unsigned char>());
-
- /**
- * Exception
- */
- DeclException1 (ExcInvalidNumberOfPartitions,
- int,
- << "The number of partitions you gave is " << arg1
- << ", but must be greater than zero.");
- /**
- * Exception
- */
- DeclException1 (ExcNonExistentSubdomain,
- int,
- << "The subdomain id " << arg1
- << " has no cells associated with it.");
- /**
- * Exception
- */
- DeclException0 (ExcTriangulationHasBeenRefined);
- /**
- * Exception
- */
- DeclException1 (ExcScalingFactorNotPositive,
- double,
- << "The scaling factor must be positive, but is " << arg1);
- /**
- * Exception
- */
- template <int N>
- DeclException1 (ExcPointNotFoundInCoarseGrid,
- Point<N>,
- << "The point <" << arg1
- << "> could not be found inside any of the "
- << "coarse grid cells.");
- /**
- * Exception
- */
- template <int N>
- DeclException1 (ExcPointNotFound,
- Point<N>,
- << "The point <" << arg1
- << "> could not be found inside any of the "
- << "subcells of a coarse grid cell.");
-
- DeclException1 (ExcVertexNotUsed,
- unsigned int,
- << "The given vertex " << arg1
- << " is not used in the given triangulation");
-
-
-};
+ /**
+ * Return the diameter of a
+ * triangulation. The diameter is
+ * computed using only the
+ * vertices, i.e. if the diameter
+ * should be larger than the
+ * maximal distance between
+ * boundary vertices due to a
+ * higher order mapping, then
+ * this function will not catch
+ * this.
+ */
+ template <int dim, int spacedim>
+ double diameter (const Triangulation<dim, spacedim> &tria);
+
+ /**
+ * Compute the volume (i.e. the dim-dimensional measure) of the
+ * triangulation. We compute the measure using the integral
+ * $\int 1 \; dx$. The integral approximated is approximated
+ * via quadrature for which we need the mapping argument.
+ *
+ * This function also works for objects of type
+ * parallel::distributed::Triangulation, in which case the
+ * function is a collective operation.
+ */
+ template <int dim, int spacedim>
+ double volume (const Triangulation<dim,spacedim> &tria,
+ const Mapping<dim,spacedim> &mapping = (StaticMappingQ1<dim,spacedim>::mapping));
+
+ /**
+ * Given a list of vertices (typically
+ * obtained using
+ * Triangulation::get_vertices) as the
+ * first, and a list of vertex indices
+ * that characterize a single cell as the
+ * second argument, return the measure
+ * (area, volume) of this cell. If this
+ * is a real cell, then you can get the
+ * same result using
+ * <code>cell-@>measure()</code>, but
+ * this function also works for cells
+ * that do not exist except that you make
+ * it up by naming its vertices from the
+ * list.
+ */
+ template <int dim>
+ double cell_measure (const std::vector<Point<dim> > &all_vertices,
+ const unsigned int (&vertex_indices)[GeometryInfo<dim>::vertices_per_cell]);
+
+ /**
+ * Remove vertices that are not
+ * referenced by any of the
+ * cells. This function is called
+ * by all <tt>GridIn::read_*</tt>
+ * functions to eliminate
+ * vertices that are listed in
+ * the input files but are not
+ * used by the cells in the input
+ * file. While these vertices
+ * should not be in the input
+ * from the beginning, they
+ * sometimes are, most often when
+ * some cells have been removed
+ * by hand without wanting to
+ * update the vertex lists, as
+ * they might be lengthy.
+ *
+ * This function is called by all
+ * <tt>GridIn::read_*</tt>
+ * functions as the triangulation
+ * class requires them to be
+ * called with used vertices
+ * only. This is so, since the
+ * vertices are copied verbatim
+ * by that class, so we have to
+ * eliminate unused vertices
+ * beforehand.
+ *
+ * Not implemented for the
+ * codimension one case.
+ */
+ template <int dim, int spacedim>
+ void delete_unused_vertices (std::vector<Point<spacedim> > &vertices,
+ std::vector<CellData<dim> > &cells,
+ SubCellData &subcelldata);
+
+ /**
+ * Remove vertices that are duplicated,
+ * due to the input of a structured grid,
+ * for example. If these vertices are not
+ * removed, the faces bounded by these
+ * vertices become part of the boundary,
+ * even if they are in the interior of
+ * the mesh.
+ *
+ * This function is called by some
+ * <tt>GridIn::read_*</tt> functions. Only
+ * the vertices with indices in @p
+ * considered_vertices are tested for
+ * equality. This speeds up the algorithm,
+ * which is quadratic and thus quite slow
+ * to begin with. However, if you wish to
+ * consider all vertices, simply pass an
+ * empty vector.
+ *
+ * Two vertices are considered equal if
+ * their difference in each coordinate
+ * direction is less than @p tol.
+ */
+ template <int dim, int spacedim>
+ void delete_duplicated_vertices (std::vector<Point<spacedim> > &all_vertices,
+ std::vector<CellData<dim> > &cells,
+ SubCellData &subcelldata,
+ std::vector<unsigned int> &considered_vertices,
+ const double tol=1e-12);
+
+ /**
+ * Transform the vertices of the given
+ * triangulation by applying the
+ * predicate to all its vertices. Since
+ * the internal consistency of a
+ * triangulation can only be guaranteed
+ * if the transformation is applied to
+ * the vertices of only one level of a
+ * hierarchically refined cells, this
+ * function may only be used if all cells
+ * of the triangulation are on the same
+ * refinement level.
+ *
+ * The predicate given as
+ * argument is used to transform
+ * each vertex. Its respective
+ * type has to offer a
+ * function-like syntax, i.e. the
+ * predicate is either an object
+ * of a type that has an
+ * <tt>operator()</tt>, or it is a
+ * pointer to the function. In
+ * either case, argument and
+ * return value have to be of
+ * type <tt>Point<dim></tt>.
+ *
+ * This function is used in the
+ * "Possibilities for extensions" section
+ * of step-38.
+ */
+ template <int dim, typename Predicate, int spacedim>
+ void transform (const Predicate &predicate,
+ Triangulation<dim,spacedim> &triangulation);
+
+ /**
+ * Shift each vertex of the
+ * triangulation by the given
+ * shift vector. This function
+ * uses the transform()
+ * function above, so the
+ * requirements on the
+ * triangulation stated there
+ * hold for this function as
+ * well.
+ */
+ template <int dim, int spacedim>
+ void shift (const Point<spacedim> &shift_vector,
+ Triangulation<dim,spacedim> &triangulation);
+
+
+ /**
+ * Rotate all vertices of the
+ * given two-dimensional
+ * triangulation in
+ * counter-clockwise sense around
+ * the origin of the coordinate
+ * system by the given angle
+ * (given in radians, rather than
+ * degrees). This function uses
+ * the transform() function
+ * above, so the requirements on
+ * the triangulation stated there
+ * hold for this function as
+ * well.
+ */
+ void rotate (const double angle,
+ Triangulation<2> &triangulation);
+
+ /**
+ * Scale the entire triangulation
+ * by the given factor. To
+ * preserve the orientation of
+ * the triangulation, the factor
+ * must be positive.
+ *
+ * This function uses the
+ * transform() function
+ * above, so the requirements on
+ * the triangulation stated there
+ * hold for this function as
+ * well.
+ */
+ template <int dim, int spacedim>
+ void scale (const double scaling_factor,
+ Triangulation<dim, spacedim> &triangulation);
+
+ /**
+ * Find and return the number of
+ * the used vertex in a given
+ * Container that is located closest
+ * to a given point @p p. The
+ * type of the first parameter
+ * may be either Triangulation,
+ * DoFHandler, hp::DoFHandler, or
+ * MGDoFHandler.
+ *
+ * @author Ralf B. Schulz, 2006
+ */
+ template <int dim, template <int, int> class Container, int spacedim>
+ unsigned int
+ find_closest_vertex (const Container<dim, spacedim> &container,
+ const Point<spacedim> &p);
+
+ /**
+ * Find and return a vector of
+ * iterators to active cells that
+ * surround a given vertex @p vertex.
+ * The type of the first parameter
+ * may be either Triangulation,
+ * DoFHandler, hp::DoFHandler, or
+ * MGDoFHandler.
+ *
+ * For locally refined grids, the
+ * vertex itself might not be a vertex
+ * of all adjacent cells, but will
+ * always be located on a face or an
+ * edge of the adjacent cells returned.
+ *
+ * @author Ralf B. Schulz,
+ * Wolfgang Bangerth, 2006
+ */
+ template<int dim, template <int, int> class Container, int spacedim>
+ std::vector<typename Container<dim,spacedim>::active_cell_iterator>
+ find_cells_adjacent_to_vertex (const Container<dim,spacedim> &container,
+ const unsigned int vertex);
+
+
+ /**
+ * Find and return an iterator to
+ * the active cell that surrounds
+ * a given point @p ref. The
+ * type of the first parameter
+ * may be either
+ * Triangulation,
+ * DoFHandler, or
+ * MGDoFHandler, i.e. we
+ * can find the cell around a
+ * point for iterators into each
+ * of these classes.
+ *
+ * This is solely a wrapper function
+ * for the @p interpolate function
+ * given below,
+ * providing backward compatibility.
+ * A Q1 mapping is used for the
+ * boundary, and the iterator to
+ * the cell in which the point
+ * resides is returned.
+ *
+ * It is recommended to use the
+ * other version of this function,
+ * as it simultaneously delivers the
+ * local coordinate of the given point
+ * without additional computational cost.
+ */
+ template <int dim, template <int,int> class Container, int spacedim>
+ typename Container<dim,spacedim>::active_cell_iterator
+ find_active_cell_around_point (const Container<dim,spacedim> &container,
+ const Point<spacedim> &p);
+
+ /**
+ * Find and return an iterator to
+ * the active cell that surrounds
+ * a given point @p p. The
+ * type of the first parameter
+ * may be either
+ * Triangulation,
+ * DoFHandler, hp::DoFHandler, or
+ * MGDoFHandler, i.e., we
+ * can find the cell around a
+ * point for iterators into each
+ * of these classes.
+ *
+ * The algorithm used in this
+ * function proceeds by first
+ * looking for vertex located
+ * closest to the given point, see
+ * find_closest_vertex(). Secondly,
+ * all adjacent cells to this point
+ * are found in the mesh, see
+ * find_cells_adjacent_to_vertex().
+ * Lastly, for each of these cells,
+ * it is tested whether the point is
+ * inside. This check is performed
+ * using arbitrary boundary mappings.
+ * Still, it is possible that due
+ * to roundoff errors, the point
+ * cannot be located exactly inside
+ * the unit cell. In this case,
+ * even points at a very small
+ * distance outside the unit cell
+ * are allowed.
+ *
+ * If a point lies on the
+ * boundary of two or more cells,
+ * then the algorithm tries to identify
+ * the cell that is of highest
+ * refinement level.
+ *
+ * The function returns an
+ * iterator to the cell, as well
+ * as the local position of the
+ * point inside the unit
+ * cell. This local position
+ * might be located slightly
+ * outside an actual unit cell,
+ * due to numerical roundoff.
+ * Therefore, the point returned
+ * by this function should
+ * be projected onto the unit cell,
+ * using GeometryInfo::project_to_unit_cell.
+ * This is not automatically performed
+ * by the algorithm.
+ */
+ template <int dim, template<int, int> class Container, int spacedim>
+ std::pair<typename Container<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ find_active_cell_around_point (const Mapping<dim,spacedim> &mapping,
+ const Container<dim,spacedim> &container,
+ const Point<spacedim> &p);
+
+ /**
+ * A version of the previous function
+ * where we use that mapping on a given
+ * cell that corresponds to the active
+ * finite element index of that
+ * cell. This is obviously only useful
+ * for hp problems, since the active
+ * finite element index for all other DoF
+ * handlers is always zero.
+ */
+ template <int dim, int spacedim>
+ std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ find_active_cell_around_point (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &container,
+ const Point<spacedim> &p);
+
+ /**
+ * Return a list of all descendents of
+ * the given cell that are active. For
+ * example, if the current cell is once
+ * refined but none of its children are
+ * any further refined, then the returned
+ * list will contain all its children.
+ *
+ * If the current cell is already active,
+ * then the returned list is empty
+ * (because the cell has no children that
+ * may be active).
+ *
+ * Since in C++ the type of the Container
+ * template argument (which can be
+ * Triangulation, DoFHandler,
+ * MGDoFHandler, or hp::DoFHandler) can
+ * not be deduced from a function call,
+ * you will have to specify it after the
+ * function name, as for example in
+ * <code>GridTools::get_active_child_cells@<DoFHandler@<dim@>
+ * @> (cell)</code>.
+ */
+ template <class Container>
+ std::vector<typename Container::active_cell_iterator>
+ get_active_child_cells (const typename Container::cell_iterator &cell);
+
+ /**
+ * Extract the active cells around a given
+ * cell @p cell and return them in the
+ * vector @p active_neighbors.
+ */
+ template <class Container>
+ void
+ get_active_neighbors (const typename Container::active_cell_iterator &cell,
+ std::vector<typename Container::active_cell_iterator> &active_neighbors);
+
+ /**
+ * Produce a sparsity pattern in which
+ * nonzero entries indicate that two
+ * cells are connected via a common
+ * face. The diagonal entries of the
+ * sparsity pattern are also set.
+ *
+ * The rows and columns refer to the
+ * cells as they are traversed in their
+ * natural order using cell iterators.
+ */
+ template <int dim, int spacedim>
+ void
+ get_face_connectivity_of_cells (const Triangulation<dim, spacedim> &triangulation,
+ SparsityPattern &connectivity);
+
+ /**
+ * Use the METIS partitioner to generate
+ * a partitioning of the active cells
+ * making up the entire domain. After
+ * calling this function, the subdomain
+ * ids of all active cells will have
+ * values between zero and
+ * @p n_partitions-1. You can access the
+ * subdomain id of a cell by using
+ * <tt>cell-@>subdomain_id()</tt>.
+ *
+ * This function will generate an error
+ * if METIS is not installed unless
+ * @p n_partitions is one. I.e., you can
+ * write a program so that it runs in the
+ * single-processor single-partition case
+ * without METIS installed, and only
+ * requires METIS when multiple
+ * partitions are required.
+ */
+ template <int dim, int spacedim>
+ void
+ partition_triangulation (const unsigned int n_partitions,
+ Triangulation<dim, spacedim> &triangulation);
+
+ /**
+ * This function does the same as the
+ * previous one, i.e. it partitions a
+ * triangulation using METIS into a
+ * number of subdomains identified by the
+ * <code>cell-@>subdomain_id()</code>
+ * flag.
+ *
+ * The difference to the previous
+ * function is the second argument, a
+ * sparsity pattern that represents the
+ * connectivity pattern between cells.
+ *
+ * While the function above builds it
+ * directly from the triangulation by
+ * considering which cells neighbor each
+ * other, this function can take a more
+ * refined connectivity graph. The
+ * sparsity pattern needs to be of size
+ * $N\times N$, where $N$ is the number
+ * of active cells in the
+ * triangulation. If the sparsity pattern
+ * contains an entry at position $(i,j)$,
+ * then this means that cells $i$ and $j$
+ * (in the order in which they are
+ * traversed by active cell iterators)
+ * are to be considered connected; METIS
+ * will then try to partition the domain
+ * in such a way that (i) the subdomains
+ * are of roughly equal size, and (ii) a
+ * minimal number of connections are
+ * broken.
+ *
+ * This function is mainly useful in
+ * cases where connections between cells
+ * exist that are not present in the
+ * triangulation alone (otherwise the
+ * previous function would be the simpler
+ * one to use). Such connections may
+ * include that certain parts of the
+ * boundary of a domain are coupled
+ * through symmetric boundary conditions
+ * or integrals (e.g. friction contact
+ * between the two sides of a crack in
+ * the domain), or if a numerical scheme
+ * is used that not only connects
+ * immediate neighbors but a larger
+ * neighborhood of cells (e.g. when
+ * solving integral equations).
+ *
+ * In addition, this function may be
+ * useful in cases where the default
+ * sparsity pattern is not entirely
+ * sufficient. This can happen because
+ * the default is to just consider face
+ * neighbors, not neighboring cells that
+ * are connected by edges or
+ * vertices. While the latter couple when
+ * using continuous finite elements, they
+ * are typically still closely connected
+ * in the neighborship graph, and METIS
+ * will not usually cut important
+ * connections in this case. However, if
+ * there are vertices in the mesh where
+ * many cells (many more than the common
+ * 4 or 6 in 2d and 3d, respectively)
+ * come together, then there will be a
+ * significant number of cells that are
+ * connected across a vertex, but several
+ * degrees removed in the connectivity
+ * graph built only using face
+ * neighbors. In a case like this, METIS
+ * may sometimes make bad decisions and
+ * you may want to build your own
+ * connectivity graph.
+ */
+ template <int dim, int spacedim>
+ void
+ partition_triangulation (const unsigned int n_partitions,
+ const SparsityPattern &cell_connection_graph,
+ Triangulation<dim,spacedim> &triangulation);
+
+ /**
+ * For each active cell, return in the
+ * output array to which subdomain (as
+ * given by the <tt>cell->subdomain_id()</tt>
+ * function) it belongs. The output array
+ * is supposed to have the right size
+ * already when calling this function.
+ *
+ * This function returns the association
+ * of each cell with one subdomain. If
+ * you are looking for the association of
+ * each @em DoF with a subdomain, use the
+ * <tt>DoFTools::get_subdomain_association</tt>
+ * function.
+ */
+ template <int dim, int spacedim>
+ void
+ get_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
+ std::vector<types::subdomain_id_t> &subdomain);
+
+ /**
+ * Count how many cells are uniquely
+ * associated with the given @p subdomain
+ * index.
+ *
+ * This function may return zero
+ * if there are no cells with the
+ * given @p subdomain index. This
+ * can happen, for example, if
+ * you try to partition a coarse
+ * mesh into more partitions (one
+ * for each processor) than there
+ * are cells in the mesh.
+ *
+ * This function returns the number of
+ * cells associated with one
+ * subdomain. If you are looking for the
+ * association of @em DoFs with this
+ * subdomain, use the
+ * <tt>DoFTools::count_dofs_with_subdomain_association</tt>
+ * function.
+ */
+ template <int dim, int spacedim>
+ unsigned int
+ count_cells_with_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
+ const types::subdomain_id_t subdomain);
+
+ /**
+ * Given two mesh containers
+ * (i.e. objects of type
+ * Triangulation, DoFHandler,
+ * hp::DoFHandler, or
+ * MGDoFHandler) that are based
+ * on the same coarse mesh, this
+ * function figures out a set of
+ * cells that are matched between
+ * the two meshes and where at
+ * most one of the meshes is more
+ * refined on this cell. In other
+ * words, it finds the smallest
+ * cells that are common to both
+ * meshes, and that together
+ * completely cover the domain.
+ *
+ * This function is useful, for
+ * example, in time-dependent or
+ * nonlinear application, where
+ * one has to integrate a
+ * solution defined on one mesh
+ * (e.g., the one from the
+ * previous time step or
+ * nonlinear iteration) against
+ * the shape functions of another
+ * mesh (the next time step, the
+ * next nonlinear iteration). If,
+ * for example, the new mesh is
+ * finer, then one has to obtain
+ * the solution on the coarse
+ * mesh (mesh_1) and interpolate
+ * it to the children of the
+ * corresponding cell of
+ * mesh_2. Conversely, if the new
+ * mesh is coarser, one has to
+ * express the coarse cell shape
+ * function by a linear
+ * combination of fine cell shape
+ * functions. In either case, one
+ * needs to loop over the finest
+ * cells that are common to both
+ * triangulations. This function
+ * returns a list of pairs of
+ * matching iterators to cells in
+ * the two meshes that can be
+ * used to this end.
+ *
+ * Note that the list of these
+ * iterators is not necessarily
+ * order, and does also not
+ * necessarily coincide with the
+ * order in which cells are
+ * traversed in one, or both, of
+ * the meshes given as arguments.
+ */
+ template <typename Container>
+ std::list<std::pair<typename Container::cell_iterator,
+ typename Container::cell_iterator> >
+ get_finest_common_cells (const Container &mesh_1,
+ const Container &mesh_2);
+
+ /**
+ * Return true if the two
+ * triangulations are based on
+ * the same coarse mesh. This is
+ * determined by checking whether
+ * they have the same number of
+ * cells on the coarsest level,
+ * and then checking that they
+ * have the same vertices.
+ *
+ * The two meshes may have
+ * different refinement histories
+ * beyond the coarse mesh.
+ */
+ template <int dim, int spacedim>
+ bool
+ have_same_coarse_mesh (const Triangulation<dim, spacedim> &mesh_1,
+ const Triangulation<dim, spacedim> &mesh_2);
+
+ /**
+ * The same function as above,
+ * but working on arguments of
+ * type DoFHandler,
+ * hp::DoFHandler, or
+ * MGDoFHandler. This function is
+ * provided to allow calling
+ * have_same_coarse_mesh for all
+ * types of containers
+ * representing triangulations or
+ * the classes built on
+ * triangulations.
+ */
+ template <typename Container>
+ bool
+ have_same_coarse_mesh (const Container &mesh_1,
+ const Container &mesh_2);
+
+ /**
+ * Return the diamater of the smallest
+ * active cell of a triangulation. See
+ * step-24 for an example
+ * of use of this function.
+ */
+ template <int dim, int spacedim>
+ double
+ minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
+
+ /**
+ * Return the diamater of the largest
+ * active cell of a triangulation.
+ */
+ template <int dim, int spacedim>
+ double
+ maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation);
+
+ /**
+ * Given the two triangulations
+ * specified as the first two
+ * arguments, create the
+ * triangulation that contains
+ * the finest cells of both
+ * triangulation and store it in
+ * the third parameter. Previous
+ * content of @p result will be
+ * deleted.
+ *
+ * @note This function is intended
+ * to create an adaptively refined
+ * triangulation that contains the
+ * <i>most refined cells</i> from
+ * two input triangulations that
+ * were derived from the <i>same </i>
+ * coarse grid by adaptive refinement.
+ * This is an operation sometimes
+ * needed when one solves for two
+ * variables of a coupled problem
+ * on separately refined meshes on
+ * the same domain (for example
+ * because these variables have
+ * boundary layers in different places)
+ * but then needs to compute something
+ * that involves both variables or
+ * wants to output the result into a
+ * single file. In both cases, in
+ * order not to lose information,
+ * the two solutions can not be
+ * interpolated onto the respectively
+ * other mesh because that may be
+ * coarser than the ones on which
+ * the variable was computed. Rather,
+ * one needs to have a mesh for the
+ * domain that is at least as fine
+ * as each of the two initial meshes.
+ * This function computes such a mesh.
+ *
+ * @note If you want to create
+ * a mesh that is the merger of
+ * two other coarse meshes, for
+ * example in order to compose a mesh
+ * for a complicated geometry from
+ * meshes for simpler geometries,
+ * take a look at
+ * GridGenerator::merge_triangulations .
+ */
+ template <int dim, int spacedim>
+ void
+ create_union_triangulation (const Triangulation<dim, spacedim> &triangulation_1,
+ const Triangulation<dim, spacedim> &triangulation_2,
+ Triangulation<dim, spacedim> &result);
+
+ /**
+ * Given a triangulation and a
+ * list of cells whose children
+ * have become distorted as a
+ * result of mesh refinement, try
+ * to fix these cells up by
+ * moving the center node around.
+ *
+ * The function returns a list of
+ * cells with distorted children
+ * that couldn't be fixed up for
+ * whatever reason. The returned
+ * list is therefore a subset of
+ * the input argument.
+ *
+ * For a definition of the
+ * concept of distorted cells,
+ * see the
+ * @ref GlossDistorted "glossary entry".
+ * The first argument passed to the
+ * current function is typically
+ * the exception thrown by the
+ * Triangulation::execute_coarsening_and_refinement
+ * function.
+ */
+ template <int dim, int spacedim>
+ typename Triangulation<dim,spacedim>::DistortedCellList
+ fix_up_distorted_child_cells (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
+ Triangulation<dim,spacedim> &triangulation);
+
+ /**
+ * This function implements a boundary
+ * subgrid extraction. Given a
+ * <dim,spacedim>-Triangulation (the
+ * "volume mesh") the function extracts a
+ * subset of its boundary (the "surface
+ * mesh"). The boundary to be extracted
+ * is specified by a list of
+ * boundary_ids. If none is specified
+ * the whole boundary will be
+ * extracted. The function is used in
+ * step-38.
+ *
+ * It also builds a mapping linking the
+ * cells on the surface mesh to the
+ * corresponding faces on the volume
+ * one. This mapping is the return value
+ * of the function.
+ *
+ * @note The function builds the surface
+ * mesh by creating a coarse mesh from
+ * the selected faces of the coarse cells
+ * of the volume mesh. It copies the
+ * boundary indicators of these faces to
+ * the cells of the coarse surface
+ * mesh. The surface mesh is then refined
+ * in the same way as the faces of the
+ * volume mesh are. In order to ensure
+ * that the surface mesh has the same
+ * vertices as the volume mesh, it is
+ * therefore important that you assign
+ * appropriate boundary objects through
+ * Triangulation::set_boundary to the
+ * surface mesh object before calling
+ * this function. If you don't, the
+ * refinement will happen under the
+ * assumption that all faces are straight
+ * (i.e using the StraightBoundary class)
+ * rather than any curved boundary object
+ * you may want to use to determine the
+ * location of new vertices.
+ *
+ * @note Oftentimes, the
+ * <code>Container</code>
+ * template type will be of kind
+ * Triangulation; in that case,
+ * the map that is returned will
+ * be between Triangulation cell
+ * iterators of the surface mesh
+ * and Triangulation face
+ * iterators of the volume
+ * mesh. However, one often needs
+ * to have this mapping between
+ * DoFHandler (or hp::DoFHandler)
+ * iterators. In that case, you
+ * can pass DoFHandler arguments
+ * as first and second parameter;
+ * the function will in that case
+ * re-build the triangulation
+ * underlying the second argument
+ * and return a map between
+ * DoFHandler iterators. However,
+ * the function will not actually
+ * distribute degrees of freedom
+ * on this newly created surface
+ * mesh.
+ *
+ * @note The algorithm outlined
+ * above assumes that all faces
+ * on higher refinement levels
+ * always have exactly the same
+ * boundary indicator as their
+ * parent face. Consequently, we
+ * can start with coarse level
+ * faces and build the surface
+ * mesh based on that. It would
+ * not be very difficult to
+ * extend the function to also
+ * copy boundary indicators from
+ * finer level faces to their
+ * corresponding surface mesh
+ * cells, for example to
+ * accomodate different geometry
+ * descriptions in the case of
+ * curved boundaries.
+ */
+ template <template <int,int> class Container, int dim, int spacedim>
+ std::map<typename Container<dim-1,spacedim>::cell_iterator,
+ typename Container<dim,spacedim>::face_iterator>
+ extract_boundary_mesh (const Container<dim,spacedim> &volume_mesh,
+ Container<dim-1,spacedim> &surface_mesh,
+ const std::set<unsigned char> &boundary_ids
+ = std::set<unsigned char>());
+
+ /**
+ * Exception
+ */
+DeclException1 (ExcInvalidNumberOfPartitions,
+ int,
+ << "The number of partitions you gave is " << arg1
+ << ", but must be greater than zero.");
+ /**
+ * Exception
+ */
+DeclException1 (ExcNonExistentSubdomain,
+ int,
+ << "The subdomain id " << arg1
+ << " has no cells associated with it.");
+ /**
+ * Exception
+ */
+DeclException0 (ExcTriangulationHasBeenRefined);
+ /**
+ * Exception
+ */
+DeclException1 (ExcScalingFactorNotPositive,
+ double,
+ << "The scaling factor must be positive, but is " << arg1);
+ /**
+ * Exception
+ */
+template <int N>
+DeclException1 (ExcPointNotFoundInCoarseGrid,
+ Point<N>,
+ << "The point <" << arg1
+ << "> could not be found inside any of the "
+ << "coarse grid cells.");
+ /**
+ * Exception
+ */
+template <int N>
+DeclException1 (ExcPointNotFound,
+ Point<N>,
+ << "The point <" << arg1
+ << "> could not be found inside any of the "
+ << "subcells of a coarse grid cell.");
+
+DeclException1 (ExcVertexNotUsed,
+ unsigned int,
+ << "The given vertex " << arg1
+ << " is not used in the given triangulation");
-
-/* ----------------- Template function --------------- */
-
-template <int dim, typename Predicate, int spacedim>
-void GridTools::transform (const Predicate &predicate,
- Triangulation<dim, spacedim> &triangulation)
-{
- // ensure that all the cells of the
- // triangulation are on the same level
- Assert (triangulation.n_levels() ==
- static_cast<unsigned int>(triangulation.begin_active()->level()+1),
- ExcMessage ("Not all cells of this triangulation are at the same "
- "refinement level, as is required for this function."));
-
- std::vector<bool> treated_vertices (triangulation.n_vertices(),
- false);
-
- // loop over all active cells, and
- // transform those vertices that
- // have not yet been touched. note
- // that we get to all vertices in
- // the triangulation by only
- // visiting the active cells.
- typename Triangulation<dim, spacedim>::active_cell_iterator
- cell = triangulation.begin_active (),
- endc = triangulation.end ();
- for (; cell!=endc; ++cell)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- if (treated_vertices[cell->vertex_index(v)] == false)
- {
- // transform this vertex
- cell->vertex(v) = predicate(cell->vertex(v));
- // and mark it as treated
- treated_vertices[cell->vertex_index(v)] = true;
- };
}
-template <class DH>
-std::vector<typename DH::active_cell_iterator>
-GridTools::get_active_child_cells (const typename DH::cell_iterator& cell)
-{
- std::vector<typename DH::active_cell_iterator> child_cells;
+/* ----------------- Template function --------------- */
- if (cell->has_children())
- {
- for (unsigned int child=0;
- child<cell->n_children(); ++child)
- if (cell->child (child)->has_children())
+namespace GridTools
+{
+ template <int dim, typename Predicate, int spacedim>
+ void transform (const Predicate &predicate,
+ Triangulation<dim, spacedim> &triangulation)
+ {
+ // ensure that all the cells of the
+ // triangulation are on the same level
+ Assert (triangulation.n_levels() ==
+ static_cast<unsigned int>(triangulation.begin_active()->level()+1),
+ ExcMessage ("Not all cells of this triangulation are at the same "
+ "refinement level, as is required for this function."));
+
+ std::vector<bool> treated_vertices (triangulation.n_vertices(),
+ false);
+
+ // loop over all active cells, and
+ // transform those vertices that
+ // have not yet been touched. note
+ // that we get to all vertices in
+ // the triangulation by only
+ // visiting the active cells.
+ typename Triangulation<dim, spacedim>::active_cell_iterator
+ cell = triangulation.begin_active (),
+ endc = triangulation.end ();
+ for (; cell!=endc; ++cell)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ if (treated_vertices[cell->vertex_index(v)] == false)
{
- const std::vector<typename DH::active_cell_iterator>
- children = get_active_child_cells<DH> (cell->child(child));
- child_cells.insert (child_cells.end(),
- children.begin(), children.end());
- }
- else
- child_cells.push_back (cell->child(child));
- }
-
- return child_cells;
-}
+ // transform this vertex
+ cell->vertex(v) = predicate(cell->vertex(v));
+ // and mark it as treated
+ treated_vertices[cell->vertex_index(v)] = true;
+ };
+ }
-template <class Container>
-void
-GridTools::get_active_neighbors(const typename Container::active_cell_iterator &cell,
- std::vector<typename Container::active_cell_iterator> &active_neighbors)
-{
- active_neighbors.clear ();
- for (unsigned int n=0; n<GeometryInfo<Container::dimension>::faces_per_cell; ++n)
- if (! cell->at_boundary(n))
+ template <class DH>
+ std::vector<typename DH::active_cell_iterator>
+ get_active_child_cells (const typename DH::cell_iterator& cell)
+ {
+ std::vector<typename DH::active_cell_iterator> child_cells;
+
+ if (cell->has_children())
{
- if (Container::dimension == 1)
- {
- // check children of neighbor. note
- // that in 1d children of the neighbor
- // may be further refined. In 1d the
- // case is simple since we know what
- // children bound to the present cell
- typename Container::cell_iterator
- neighbor_child = cell->neighbor(n);
- if (!neighbor_child->active())
- {
- while (neighbor_child->has_children())
- neighbor_child = neighbor_child->child (n==0 ? 1 : 0);
-
- Assert (neighbor_child->neighbor(n==0 ? 1 : 0)==cell,
- ExcInternalError());
- }
- active_neighbors.push_back (neighbor_child);
- }
- else
- {
- if (cell->face(n)->has_children())
- // this neighbor has children. find
- // out which border to the present
- // cell
- for (unsigned int c=0; c<cell->face(n)->number_of_children(); ++c)
- active_neighbors.push_back (cell->neighbor_child_on_subface(n,c));
- else
- {
- // the neighbor must be active
- // himself
- Assert(cell->neighbor(n)->active(), ExcInternalError());
- active_neighbors.push_back(cell->neighbor(n));
- }
- }
+ for (unsigned int child=0;
+ child<cell->n_children(); ++child)
+ if (cell->child (child)->has_children())
+ {
+ const std::vector<typename DH::active_cell_iterator>
+ children = get_active_child_cells<DH> (cell->child(child));
+ child_cells.insert (child_cells.end(),
+ children.begin(), children.end());
+ }
+ else
+ child_cells.push_back (cell->child(child));
}
-}
+ return child_cells;
+ }
-// declaration of explicit specializations
-
-template <>
-double
-GridTools::cell_measure<3>(const std::vector<Point<3> > &all_vertices,
- const unsigned int (&vertex_indices) [GeometryInfo<3>::vertices_per_cell]);
+ template <class Container>
+ void
+ get_active_neighbors(const typename Container::active_cell_iterator &cell,
+ std::vector<typename Container::active_cell_iterator> &active_neighbors)
+ {
+ active_neighbors.clear ();
+ for (unsigned int n=0; n<GeometryInfo<Container::dimension>::faces_per_cell; ++n)
+ if (! cell->at_boundary(n))
+ {
+ if (Container::dimension == 1)
+ {
+ // check children of neighbor. note
+ // that in 1d children of the neighbor
+ // may be further refined. In 1d the
+ // case is simple since we know what
+ // children bound to the present cell
+ typename Container::cell_iterator
+ neighbor_child = cell->neighbor(n);
+ if (!neighbor_child->active())
+ {
+ while (neighbor_child->has_children())
+ neighbor_child = neighbor_child->child (n==0 ? 1 : 0);
+
+ Assert (neighbor_child->neighbor(n==0 ? 1 : 0)==cell,
+ ExcInternalError());
+ }
+ active_neighbors.push_back (neighbor_child);
+ }
+ else
+ {
+ if (cell->face(n)->has_children())
+ // this neighbor has children. find
+ // out which border to the present
+ // cell
+ for (unsigned int c=0; c<cell->face(n)->number_of_children(); ++c)
+ active_neighbors.push_back (cell->neighbor_child_on_subface(n,c));
+ else
+ {
+ // the neighbor must be active
+ // himself
+ Assert(cell->neighbor(n)->active(), ExcInternalError());
+ active_neighbors.push_back(cell->neighbor(n));
+ }
+ }
+ }
+ }
-template <>
-double
-GridTools::cell_measure<2>(const std::vector<Point<2> > &all_vertices,
- const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell]);
-// double
-// GridTools::cell_measure<2,3>(const std::vector<Point<3> > &all_vertices,
-// const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell]);
+// declaration of explicit specializations
+ template <>
+ double
+ cell_measure<3>(const std::vector<Point<3> > &all_vertices,
+ const unsigned int (&vertex_indices) [GeometryInfo<3>::vertices_per_cell]);
+ template <>
+ double
+ cell_measure<2>(const std::vector<Point<2> > &all_vertices,
+ const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell]);
+}
//---------------------------------------------------------------------------
// $Id$
//
-// Copyright (C) 2005, 2006, 2007, 2008, 2010 by the deal.II authors
+// Copyright (C) 2005, 2006, 2007, 2008, 2010, 2011 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
* objects. See there and the documentation of the member functions
* for more information.
*
- * All member functions are static, so there is no need to create an
- * object of class MGTools.
- *
* @author Wolfgang Bangerth, Guido Kanschat, 1999 - 2005
*/
-class MGTools
+namespace MGTools
{
- public:
- /**
- * Compute row length vector for
- * multilevel methods.
- */
- template <int dim, int spacedim>
- static
- void compute_row_length_vector(
- const MGDoFHandler<dim,spacedim>& dofs,
- const unsigned int level,
- std::vector<unsigned int>& row_lengths,
- const DoFTools::Coupling flux_couplings = DoFTools::none);
+ /**
+ * Compute row length vector for
+ * multilevel methods.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_row_length_vector(const MGDoFHandler<dim,spacedim>& dofs,
+ const unsigned int level,
+ std::vector<unsigned int>& row_lengths,
+ const DoFTools::Coupling flux_couplings = DoFTools::none);
+
+ /**
+ * Compute row length vector for
+ * multilevel methods with
+ * optimization for block
+ * couplings.
+ */
+ template <int dim, int spacedim>
+ void
+ compute_row_length_vector(const MGDoFHandler<dim,spacedim>& dofs,
+ const unsigned int level,
+ std::vector<unsigned int>& row_lengths,
+ const Table<2,DoFTools::Coupling>& couplings,
+ const Table<2,DoFTools::Coupling>& flux_couplings);
+
+ /**
+ * Write the sparsity structure
+ * of the matrix belonging to the
+ * specified @p level. The sparsity pattern
+ * is not compressed, so before
+ * creating the actual matrix
+ * you have to compress the
+ * matrix yourself, using
+ * <tt>SparseMatrixStruct::compress()</tt>.
+ *
+ * There is no need to consider
+ * hanging nodes here, since only
+ * one level is considered.
+ */
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof_handler,
+ SparsityPattern &sparsity,
+ const unsigned int level);
- /**
- * Compute row length vector for
- * multilevel methods with
- * optimization for block
- * couplings.
- */
- template <int dim, int spacedim>
- static
- void compute_row_length_vector(
- const MGDoFHandler<dim,spacedim>& dofs,
- const unsigned int level,
- std::vector<unsigned int>& row_lengths,
- const Table<2,DoFTools::Coupling>& couplings,
- const Table<2,DoFTools::Coupling>& flux_couplings);
+ /**
+ * Make a sparsity pattern including fluxes
+ * of discontinuous Galerkin methods.
+ * @ref make_sparsity_pattern
+ * @ref DoFTools
+ */
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof_handler,
+ SparsityPattern &sparsity,
+ const unsigned int level);
- /**
- * Write the sparsity structure
- * of the matrix belonging to the
- * specified @p level. The sparsity pattern
- * is not compressed, so before
- * creating the actual matrix
- * you have to compress the
- * matrix yourself, using
- * <tt>SparseMatrixStruct::compress()</tt>.
- *
- * There is no need to consider
- * hanging nodes here, since only
- * one level is considered.
- */
- template <int dim, class SparsityPattern, int spacedim>
- static void
- make_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof_handler,
- SparsityPattern &sparsity,
- const unsigned int level);
+ /**
+ * Create sparsity pattern for
+ * the fluxes at refinement
+ * edges. The matrix maps a
+ * function of the fine level
+ * space @p level to the coarser
+ * space.
+ *
+ * make_flux_sparsity_pattern()
+ */
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern_edge (const MGDoFHandler<dim,spacedim> &dof_handler,
+ SparsityPattern &sparsity,
+ const unsigned int level);
+ /**
+ * This function does the same as
+ * the other with the same name,
+ * but it gets two additional
+ * coefficient matrices. A matrix
+ * entry will only be generated
+ * for two basis functions, if
+ * there is a non-zero entry
+ * linking their associated
+ * components in the coefficient
+ * matrix.
+ *
+ * There is one matrix for
+ * couplings in a cell and one
+ * for the couplings occuring in
+ * fluxes.
+ */
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level,
+ const Table<2,DoFTools::Coupling> &int_mask,
+ const Table<2,DoFTools::Coupling> &flux_mask);
- /**
- * Make a sparsity pattern including fluxes
- * of discontinuous Galerkin methods.
- * @ref make_sparsity_pattern
- * @ref DoFTools
- */
- template <int dim, class SparsityPattern, int spacedim>
- static void
- make_flux_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof_handler,
- SparsityPattern &sparsity,
- const unsigned int level);
+ /**
+ * Create sparsity pattern for
+ * the fluxes at refinement
+ * edges. The matrix maps a
+ * function of the fine level
+ * space @p level to the coarser
+ * space. This is the version
+ * restricting the pattern to the
+ * elements actually needed.
+ *
+ * make_flux_sparsity_pattern()
+ */
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern_edge (const MGDoFHandler<dim,spacedim> &dof_handler,
+ SparsityPattern &sparsity,
+ const unsigned int level,
+ const Table<2,DoFTools::Coupling> &flux_mask);
- /**
- * Create sparsity pattern for
- * the fluxes at refinement
- * edges. The matrix maps a
- * function of the fine level
- * space @p level to the coarser
- * space.
- *
- * make_flux_sparsity_pattern()
- */
- template <int dim, class SparsityPattern, int spacedim>
- static void
- make_flux_sparsity_pattern_edge (const MGDoFHandler<dim,spacedim> &dof_handler,
- SparsityPattern &sparsity,
- const unsigned int level);
- /**
- * This function does the same as
- * the other with the same name,
- * but it gets two additional
- * coefficient matrices. A matrix
- * entry will only be generated
- * for two basis functions, if
- * there is a non-zero entry
- * linking their associated
- * components in the coefficient
- * matrix.
- *
- * There is one matrix for
- * couplings in a cell and one
- * for the couplings occuring in
- * fluxes.
- */
- template <int dim, class SparsityPattern, int spacedim>
- static void
- make_flux_sparsity_pattern (const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level,
- const Table<2,DoFTools::Coupling> &int_mask,
- const Table<2,DoFTools::Coupling> &flux_mask);
+ /**
+ * Count the dofs block-wise
+ * on each level.
+ *
+ * Result is a vector containing
+ * for each level a vector
+ * containing the number of dofs
+ * for each block (access is
+ * <tt>result[level][block]</tt>).
+ */
+ template <int dim, int spacedim>
+ void
+ count_dofs_per_block (const MGDoFHandler<dim,spacedim> &mg_dof,
+ std::vector<std::vector<unsigned int> > &result,
+ std::vector<unsigned int> target_block = std::vector<unsigned int>());
- /**
- * Create sparsity pattern for
- * the fluxes at refinement
- * edges. The matrix maps a
- * function of the fine level
- * space @p level to the coarser
- * space. This is the version
- * restricting the pattern to the
- * elements actually needed.
- *
- * make_flux_sparsity_pattern()
- */
- template <int dim, class SparsityPattern, int spacedim>
- static void
- make_flux_sparsity_pattern_edge (const MGDoFHandler<dim,spacedim> &dof_handler,
- SparsityPattern &sparsity,
- const unsigned int level,
- const Table<2,DoFTools::Coupling> &flux_mask);
+ /**
+ * Count the dofs component-wise
+ * on each level.
+ *
+ * Result is a vector containing
+ * for each level a vector
+ * containing the number of dofs
+ * for each component (access is
+ * <tt>result[level][component]</tt>).
+ */
+ template <int dim, int spacedim>
+ void
+ count_dofs_per_component (const MGDoFHandler<dim,spacedim> &mg_dof,
+ std::vector<std::vector<unsigned int> > &result,
+ const bool only_once = false,
+ std::vector<unsigned int> target_component = std::vector<unsigned int>());
- /**
- * Count the dofs block-wise
- * on each level.
- *
- * Result is a vector containing
- * for each level a vector
- * containing the number of dofs
- * for each block (access is
- * <tt>result[level][block]</tt>).
- */
- template <int dim, int spacedim>
- static void count_dofs_per_block (
- const MGDoFHandler<dim,spacedim> &mg_dof,
- std::vector<std::vector<unsigned int> > &result,
- std::vector<unsigned int> target_block = std::vector<unsigned int>());
+ /**
+ * @deprecated Wrapper for the
+ * other function with same name,
+ * introduced for compatibility.
+ */
+ template <int dim, int spacedim>
+ void
+ count_dofs_per_component (const MGDoFHandler<dim,spacedim> &mg_dof,
+ std::vector<std::vector<unsigned int> > &result,
+ std::vector<unsigned int> target_component);
- /**
- * Count the dofs component-wise
- * on each level.
- *
- * Result is a vector containing
- * for each level a vector
- * containing the number of dofs
- * for each component (access is
- * <tt>result[level][component]</tt>).
- */
- template <int dim, int spacedim>
- static void count_dofs_per_component (
- const MGDoFHandler<dim,spacedim> &mg_dof,
- std::vector<std::vector<unsigned int> > &result,
- const bool only_once = false,
- std::vector<unsigned int> target_component = std::vector<unsigned int>());
+ /**
+ * Generate a list of those
+ * degrees of freedom at the
+ * boundary which should be
+ * eliminated from the matrix.
+ *
+ * This is the multilevel
+ * equivalent of
+ * VectorTools::interpolate_boundary_values,
+ * but since the multilevel
+ * method does not have its own
+ * right hand side, the function
+ * values are ignored.
+ *
+ * @arg <tt>boundary_indices</tt>
+ * is a vector which on return
+ * contains all indices of
+ * boundary constraint degrees of
+ * freedom for each level. Its
+ * length has to match the number
+ * of levels.
+ */
+ template <int dim, int spacedim>
+ void
+ make_boundary_list (const MGDoFHandler<dim,spacedim> &mg_dof,
+ const typename FunctionMap<dim>::type &function_map,
+ std::vector<std::set<unsigned int> > &boundary_indices,
+ const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * @deprecated Wrapper for the
- * other function with same name,
- * introduced for compatibility.
- */
- template <int dim, int spacedim>
- static void count_dofs_per_component (
- const MGDoFHandler<dim,spacedim> &mg_dof,
- std::vector<std::vector<unsigned int> > &result,
- std::vector<unsigned int> target_component);
+ /**
+ * The same function as above, but return
+ * an IndexSet rather than a
+ * std::set<unsigned int> on each level.
+ */
+ template <int dim, int spacedim>
+ void
+ make_boundary_list (const MGDoFHandler<dim,spacedim> &mg_dof,
+ const typename FunctionMap<dim>::type &function_map,
+ std::vector<IndexSet> &boundary_indices,
+ const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Generate a list of those
- * degrees of freedom at the
- * boundary which should be
- * eliminated from the matrix.
- *
- * This is the multilevel
- * equivalent of
- * VectorTools::interpolate_boundary_values,
- * but since the multilevel
- * method does not have its own
- * right hand side, the function
- * values are ignored.
- *
- * @arg <tt>boundary_indices</tt>
- * is a vector which on return
- * contains all indices of
- * boundary constraint degrees of
- * freedom for each level. Its
- * length has to match the number
- * of levels.
- */
- template <int dim, int spacedim>
- static
- void
- make_boundary_list (const MGDoFHandler<dim,spacedim> &mg_dof,
- const typename FunctionMap<dim>::type &function_map,
- std::vector<std::set<unsigned int> > &boundary_indices,
- const std::vector<bool> &component_mask = std::vector<bool>());
+ /**
+ * Maybe no longer needed.
+ */
- /**
- * The same function as above, but return
- * an IndexSet rather than a
- * std::set<unsigned int> on each level.
- */
- template <int dim, int spacedim>
- static
- void
- make_boundary_list (const MGDoFHandler<dim,spacedim> &mg_dof,
- const typename FunctionMap<dim>::type &function_map,
- std::vector<IndexSet> &boundary_indices,
- const std::vector<bool> &component_mask = std::vector<bool>());
-
- /**
- * Maybe no longer needed.
- */
+ template <typename number>
+ void
+ apply_boundary_values (const std::set<unsigned int> &boundary_dofs,
+ SparseMatrix<number>& matrix,
+ const bool preserve_symmetry,
+ const bool ignore_zeros = false);
- template <typename number>
- static void apply_boundary_values (
- const std::set<unsigned int> &boundary_dofs,
- SparseMatrix<number>& matrix,
- const bool preserve_symmetry,
- const bool ignore_zeros = false);
+ template <typename number>
+ void
+ apply_boundary_values (const std::set<unsigned int>& boundary_dofs,
+ BlockSparseMatrix<number>& matrix,
+ const bool preserve_symmetry);
- template <typename number>
- static void apply_boundary_values (
- const std::set<unsigned int>& boundary_dofs,
- BlockSparseMatrix<number>& matrix,
- const bool preserve_symmetry);
+ /**
+ * For each level in a multigrid
+ * hierarchy, produce a boolean
+ * mask that indicates which of
+ * the degrees of freedom are
+ * along interfaces of this level
+ * to cells that only exist on
+ * coarser levels. The function
+ * returns the subset of these
+ * indices in the last argument
+ * that are not only on interior
+ * interfaces (i.e. between cells
+ * of a given level and adjacent
+ * coarser levels) but also on
+ * the external boundary of the
+ * domain.
+ */
+ template <int dim, int spacedim>
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs,
+ std::vector<std::vector<bool> > &boundary_interface_dofs);
- /**
- * For each level in a multigrid
- * hierarchy, produce a boolean
- * mask that indicates which of
- * the degrees of freedom are
- * along interfaces of this level
- * to cells that only exist on
- * coarser levels. The function
- * returns the subset of these
- * indices in the last argument
- * that are not only on interior
- * interfaces (i.e. between cells
- * of a given level and adjacent
- * coarser levels) but also on
- * the external boundary of the
- * domain.
- */
- template <int dim, int spacedim>
- static
- void
- extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs,
- std::vector<std::vector<bool> > &boundary_interface_dofs);
+ /**
+ * Does the same as the function above,
+ * but fills only the interface_dofs.
+ */
+ template <int dim, int spacedim>
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs);
+}
- /**
- * Does the same as the function above,
- * but fills only the interface_dofs.
- */
- template <int dim, int spacedim>
- static
- void
- extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs);
-};
-/*@}*/
DEAL_II_NAMESPACE_CLOSE
//TODO: Move documentation of functions to the functions!
-//TODO: (Re)move the basic course on Sobolev spaces
/**
- * Provide a class which offers some operations on vectors. Amoung
+ * Provide a namespace which offers some operations on vectors. Amoung
* these are assembling of standard vectors, integration of the
* difference of a finite element solution and a continuous function,
* interpolations and projections of continuous functions to the
* @ingroup numerics
* @author Wolfgang Bangerth, Ralf Hartmann, Guido Kanschat, 1998, 1999, 2000, 2001
*/
-class VectorTools
+namespace VectorTools
{
- public:
-
- /**
- * Denote which norm/integral is
- * to be computed by the
- * integrate_difference()
- * function of this class. The
- * following possibilities are
- * implemented:
- */
+ /**
+ * Denote which norm/integral is
+ * to be computed by the
+ * integrate_difference()
+ * function of this class. The
+ * following possibilities are
+ * implemented:
+ */
enum NormType
- {
- /**
- * The function or
- * difference of functions
- * is integrated on each
- * cell.
- */
- mean,
- /**
- * The absolute value of
- * the function is
- * integrated.
- */
- L1_norm,
- /**
- * The square of the
- * function is integrated
- * and the the square root
- * of the result is
- * computed on each cell.
- */
- L2_norm,
- /**
- * The absolute value to
- * the <i>p</i>th power is
- * integrated and the pth
- * root is computed on each
- * cell. The exponent
- * <i>p</i> is the last
- * parameter of the
- * function.
- */
- Lp_norm,
- /**
- * The maximum absolute
- * value of the function.
- */
- Linfty_norm,
- /**
- * #L2_norm of the gradient.
- */
- H1_seminorm,
- /**
- * The square of this norm
- * is the square of the
- * #L2_norm plus the square
- * of the #H1_seminorm.
- */
- H1_norm,
- /**
- * #Lp_norm of the gradient.
- */
- W1p_seminorm,
- /**
- * same as #H1_norm for
- * <i>L<sup>p</sup></i>.
- */
- W1p_norm,
- /**
- * #Linfty_norm of the gradient.
- */
- W1infty_seminorm,
- /**
- * same as #H1_norm for
- * <i>L<sup>infty</sup></i>.
- */
- W1infty_norm
-
- };
+ {
+ /**
+ * The function or
+ * difference of functions
+ * is integrated on each
+ * cell.
+ */
+ mean,
+ /**
+ * The absolute value of
+ * the function is
+ * integrated.
+ */
+ L1_norm,
+ /**
+ * The square of the
+ * function is integrated
+ * and the the square root
+ * of the result is
+ * computed on each cell.
+ */
+ L2_norm,
+ /**
+ * The absolute value to
+ * the <i>p</i>th power is
+ * integrated and the pth
+ * root is computed on each
+ * cell. The exponent
+ * <i>p</i> is the last
+ * parameter of the
+ * function.
+ */
+ Lp_norm,
+ /**
+ * The maximum absolute
+ * value of the function.
+ */
+ Linfty_norm,
+ /**
+ * #L2_norm of the gradient.
+ */
+ H1_seminorm,
+ /**
+ * The square of this norm
+ * is the square of the
+ * #L2_norm plus the square
+ * of the #H1_seminorm.
+ */
+ H1_norm,
+ /**
+ * #Lp_norm of the gradient.
+ */
+ W1p_seminorm,
+ /**
+ * same as #H1_norm for
+ * <i>L<sup>p</sup></i>.
+ */
+ W1p_norm,
+ /**
+ * #Linfty_norm of the gradient.
+ */
+ W1infty_seminorm,
+ /**
+ * same as #H1_norm for
+ * <i>L<sup>infty</sup></i>.
+ */
+ W1infty_norm
+
+ };
/**
* @name Interpolation and projection
*/
- //@{
- /**
- * Compute the interpolation of
- * @p function at the support
- * points to the finite element
- * space. It is assumed that the
- * number of components of
- * @p function matches that of
- * the finite element used by
- * @p dof.
- *
- * Note that you may have to call
- * <tt>hanging_nodes.distribute(vec)</tt>
- * with the hanging nodes from
- * space @p dof afterwards, to
- * make the result continuous
- * again.
- *
- * The template argument <code>DH</code>
- * may either be of type DoFHandler or
- * hp::DoFHandler.
- *
- * See the general documentation
- * of this class for further
- * information.
- *
- * @todo The @p mapping argument should be
- * replaced by a hp::MappingCollection in
- * case of a hp::DoFHandler.
- */
+ //@{
+ /**
+ * Compute the interpolation of
+ * @p function at the support
+ * points to the finite element
+ * space. It is assumed that the
+ * number of components of
+ * @p function matches that of
+ * the finite element used by
+ * @p dof.
+ *
+ * Note that you may have to call
+ * <tt>hanging_nodes.distribute(vec)</tt>
+ * with the hanging nodes from
+ * space @p dof afterwards, to
+ * make the result continuous
+ * again.
+ *
+ * The template argument <code>DH</code>
+ * may either be of type DoFHandler or
+ * hp::DoFHandler.
+ *
+ * See the general documentation
+ * of this class for further
+ * information.
+ *
+ * @todo The @p mapping argument should be
+ * replaced by a hp::MappingCollection in
+ * case of a hp::DoFHandler.
+ */
template <class VECTOR, class DH>
- static void interpolate (const Mapping<DH::dimension,DH::space_dimension> &mapping,
- const DH &dof,
- const Function<DH::space_dimension> &function,
- VECTOR &vec);
-
- /**
- * Calls the @p interpolate()
- * function above with
- * <tt>mapping=MappingQ1@<dim>@()</tt>.
- */
+ void interpolate (const Mapping<DH::dimension,DH::space_dimension> &mapping,
+ const DH &dof,
+ const Function<DH::space_dimension> &function,
+ VECTOR &vec);
+
+ /**
+ * Calls the @p interpolate()
+ * function above with
+ * <tt>mapping=MappingQ1@<dim>@()</tt>.
+ */
template <class VECTOR, class DH>
- static void interpolate (const DH &dof,
- const Function<DH::space_dimension> &function,
- VECTOR &vec);
-
- /**
- * Interpolate different finite
- * element spaces. The
- * interpolation of vector
- * @p data_1 is executed from the
- * FE space represented by
- * @p dof_1 to the vector @p data_2
- * on FE space @p dof_2. The
- * interpolation on each cell is
- * represented by the matrix
- * @p transfer. Curved boundaries
- * are neglected so far.
- *
- * Note that you may have to call
- * <tt>hanging_nodes.distribute(data_2)</tt>
- * with the hanging nodes from
- * space @p dof_2 afterwards, to
- * make the result continuous
- * again.
- *
- * @note Instantiations for this template
- * are provided for some vector types
- * (see the general documentation of the
- * class), but only the same vector for
- * InVector and OutVector. Other
- * combinations must be instantiated by
- * hand.
- */
+ void interpolate (const DH &dof,
+ const Function<DH::space_dimension> &function,
+ VECTOR &vec);
+
+ /**
+ * Interpolate different finite
+ * element spaces. The
+ * interpolation of vector
+ * @p data_1 is executed from the
+ * FE space represented by
+ * @p dof_1 to the vector @p data_2
+ * on FE space @p dof_2. The
+ * interpolation on each cell is
+ * represented by the matrix
+ * @p transfer. Curved boundaries
+ * are neglected so far.
+ *
+ * Note that you may have to call
+ * <tt>hanging_nodes.distribute(data_2)</tt>
+ * with the hanging nodes from
+ * space @p dof_2 afterwards, to
+ * make the result continuous
+ * again.
+ *
+ * @note Instantiations for this template
+ * are provided for some vector types
+ * (see the general documentation of the
+ * class), but only the same vector for
+ * InVector and OutVector. Other
+ * combinations must be instantiated by
+ * hand.
+ */
template <int dim, class InVector, class OutVector, int spacedim>
- static void interpolate (const DoFHandler<dim,spacedim> &dof_1,
- const DoFHandler<dim,spacedim> &dof_2,
- const FullMatrix<double> &transfer,
- const InVector &data_1,
- OutVector &data_2);
-
- /**
- * Compute the projection of
- * @p function to the finite element space.
- *
- * By default, projection to the boundary
- * and enforcement of zero boundary values
- * are disabled. The ordering of arguments
- * to this function is such that you need
- * not give a second quadrature formula if
- * you don't want to project to the
- * boundary first, but that you must if you
- * want to do so.
- *
- * This function needs the mass
- * matrix of the finite element
- * space on the present grid. To
- * this end, the mass matrix is
- * assembled exactly using
- * MatrixTools::create_mass_matrix. This
- * function performs numerical
- * quadrature using the given
- * quadrature rule; you should
- * therefore make sure that the
- * given quadrature formula is
- * also sufficient for the
- * integration of the mass
- * matrix.
- *
- * See the general documentation of this
- * class for further information.
- *
- * In 1d, the default value of
- * the boundary quadrature
- * formula is an invalid object
- * since integration on the
- * boundary doesn't happen in
- * 1d.
- */
+ void interpolate (const DoFHandler<dim,spacedim> &dof_1,
+ const DoFHandler<dim,spacedim> &dof_2,
+ const FullMatrix<double> &transfer,
+ const InVector &data_1,
+ OutVector &data_2);
+
+ /**
+ * Compute the projection of
+ * @p function to the finite element space.
+ *
+ * By default, projection to the boundary
+ * and enforcement of zero boundary values
+ * are disabled. The ordering of arguments
+ * to this function is such that you need
+ * not give a second quadrature formula if
+ * you don't want to project to the
+ * boundary first, but that you must if you
+ * want to do so.
+ *
+ * This function needs the mass
+ * matrix of the finite element
+ * space on the present grid. To
+ * this end, the mass matrix is
+ * assembled exactly using
+ * MatrixTools::create_mass_matrix. This
+ * function performs numerical
+ * quadrature using the given
+ * quadrature rule; you should
+ * therefore make sure that the
+ * given quadrature formula is
+ * also sufficient for the
+ * integration of the mass
+ * matrix.
+ *
+ * See the general documentation of this
+ * class for further information.
+ *
+ * In 1d, the default value of
+ * the boundary quadrature
+ * formula is an invalid object
+ * since integration on the
+ * boundary doesn't happen in
+ * 1d.
+ */
template <int dim, class VECTOR, int spacedim>
- static void project (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const ConstraintMatrix &constraints,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &function,
- VECTOR &vec,
- const bool enforce_zero_boundary = false,
- const Quadrature<dim-1> &q_boundary = (dim > 1 ?
- QGauss<dim-1>(2) :
- Quadrature<dim-1>(0)),
- const bool project_to_boundary_first = false);
-
- /**
- * Calls the project()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
+ void project (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const ConstraintMatrix &constraints,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &function,
+ VECTOR &vec,
+ const bool enforce_zero_boundary = false,
+ const Quadrature<dim-1> &q_boundary = (dim > 1 ?
+ QGauss<dim-1>(2) :
+ Quadrature<dim-1>(0)),
+ const bool project_to_boundary_first = false);
+
+ /**
+ * Calls the project()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
template <int dim, class VECTOR, int spacedim>
- static void project (const DoFHandler<dim,spacedim> &dof,
- const ConstraintMatrix &constraints,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &function,
- VECTOR &vec,
- const bool enforce_zero_boundary = false,
- const Quadrature<dim-1> &q_boundary = (dim > 1 ?
- QGauss<dim-1>(2) :
- Quadrature<dim-1>(0)),
- const bool project_to_boundary_first = false);
-
- /**
- * Prepare Dirichlet boundary
- * conditions. Make up the list
- * of degrees of freedom subject
- * to Dirichlet boundary
- * conditions and the values to
- * be assigned to them, by
- * interpolation around the
- * boundary. If the
- * @p boundary_values contained
- * values before, the new ones
- * are added, or the old ones
- * overwritten if a node of the
- * boundary part to be used
- * was already in the
- * map of boundary values.
- *
- * The parameter
- * @p boundary_component
- * corresponds to the number
- * @p boundary_indicator of the
- * face. 255 is an illegal
- * value, since it is reserved
- * for interior faces.
- *
- * The flags in the last
- * parameter, @p component_mask
- * denote which components of the
- * finite element space shall be
- * interpolated. If it is left as
- * specified by the default value
- * (i.e. an empty array), all
- * components are
- * interpolated. If it is
- * different from the default
- * value, it is assumed that the
- * number of entries equals the
- * number of components in the
- * boundary functions and the
- * finite element, and those
- * components in the given
- * boundary function will be used
- * for which the respective flag
- * was set in the component mask.
- *
- * It is assumed that the number
- * of components of the function
- * in @p boundary_function matches that
- * of the finite element used by
- * @p dof.
- *
- * If the finite element used has
- * shape functions that are
- * non-zero in more than one
- * component (in deal.II speak:
- * they are non-primitive), then
- * these components can presently
- * not be used for interpolating
- * boundary values. Thus, the
- * elements in the component mask
- * corresponding to the
- * components of these
- * non-primitive shape functions
- * must be @p false.
- *
- * See the general doc for more
- * information.
- */
+ void project (const DoFHandler<dim,spacedim> &dof,
+ const ConstraintMatrix &constraints,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &function,
+ VECTOR &vec,
+ const bool enforce_zero_boundary = false,
+ const Quadrature<dim-1> &q_boundary = (dim > 1 ?
+ QGauss<dim-1>(2) :
+ Quadrature<dim-1>(0)),
+ const bool project_to_boundary_first = false);
+
+ /**
+ * Prepare Dirichlet boundary
+ * conditions. Make up the list
+ * of degrees of freedom subject
+ * to Dirichlet boundary
+ * conditions and the values to
+ * be assigned to them, by
+ * interpolation around the
+ * boundary. If the
+ * @p boundary_values contained
+ * values before, the new ones
+ * are added, or the old ones
+ * overwritten if a node of the
+ * boundary part to be used
+ * was already in the
+ * map of boundary values.
+ *
+ * The parameter
+ * @p boundary_component
+ * corresponds to the number
+ * @p boundary_indicator of the
+ * face. 255 is an illegal
+ * value, since it is reserved
+ * for interior faces.
+ *
+ * The flags in the last
+ * parameter, @p component_mask
+ * denote which components of the
+ * finite element space shall be
+ * interpolated. If it is left as
+ * specified by the default value
+ * (i.e. an empty array), all
+ * components are
+ * interpolated. If it is
+ * different from the default
+ * value, it is assumed that the
+ * number of entries equals the
+ * number of components in the
+ * boundary functions and the
+ * finite element, and those
+ * components in the given
+ * boundary function will be used
+ * for which the respective flag
+ * was set in the component mask.
+ *
+ * It is assumed that the number
+ * of components of the function
+ * in @p boundary_function matches that
+ * of the finite element used by
+ * @p dof.
+ *
+ * If the finite element used has
+ * shape functions that are
+ * non-zero in more than one
+ * component (in deal.II speak:
+ * they are non-primitive), then
+ * these components can presently
+ * not be used for interpolating
+ * boundary values. Thus, the
+ * elements in the component mask
+ * corresponding to the
+ * components of these
+ * non-primitive shape functions
+ * must be @p false.
+ *
+ * See the general doc for more
+ * information.
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const Mapping<DH::dimension,DH::space_dimension> &mapping,
const DH &dof,
std::map<unsigned int,double> &boundary_values,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * @deprecated This function exists mainly
- * for backward compatibility.
- *
- * Same function as above, but
- * taking only one pair of
- * boundary indicator and
- * corresponding boundary
- * function. Calls the other
- * function with remapped
- * arguments.
- *
- */
+ /**
+ * @deprecated This function exists mainly
+ * for backward compatibility.
+ *
+ * Same function as above, but
+ * taking only one pair of
+ * boundary indicator and
+ * corresponding boundary
+ * function. Calls the other
+ * function with remapped
+ * arguments.
+ *
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const Mapping<DH::dimension,DH::space_dimension> &mapping,
const DH &dof,
std::map<unsigned int,double> &boundary_values,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Calls the other
- * interpolate_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
+ /**
+ * Calls the other
+ * interpolate_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const DH &dof,
const unsigned char boundary_component,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Calls the other
- * interpolate_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
+ /**
+ * Calls the other
+ * interpolate_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const DH &dof,
const typename FunctionMap<DH::space_dimension>::type &function_map,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Insert the (algebraic) constraints due
- * to Dirichlet boundary conditions into
- * a ConstraintMatrix @p
- * constraints. This function identifies
- * the degrees of freedom subject to
- * Dirichlet boundary conditions, adds
- * them to the list of constrained DoFs
- * in @p constraints and sets the
- * respective inhomogeneity to the value
- * interpolated around the boundary. If
- * this routine encounters a DoF that
- * already is constrained (for instance
- * by a hanging node constraint, see
- * below, or any other type of
- * constraint, e.g. from periodic
- * boundary conditions), the old setting
- * of the constraint (dofs the entry is
- * constrained to, inhomogeneities) is
- * kept and nothing happens.
- *
- * @note When combining adaptively
- * refined meshes with hanging node
- * constraints and boundary conditions
- * like from the current function within
- * one ConstraintMatrix object, the
- * hanging node constraints should always
- * be set first, and then the boundary
- * conditions since boundary conditions
- * are not set in the second operation on
- * degrees of freedom that are already
- * constrained. This makes sure that the
- * discretization remains conforming as
- * is needed. See the discussion on
- * conflicting constraints in the module
- * on @ref constraints .
- *
- * The parameter @p boundary_component
- * corresponds to the number @p
- * boundary_indicator of the face. 255
- * is an illegal value, since it is
- * reserved for interior faces.
- *
- * The flags in the last parameter, @p
- * component_mask denote which
- * components of the finite element
- * space shall be interpolated. If it
- * is left as specified by the default
- * value (i.e. an empty array), all
- * components are interpolated. If it
- * is different from the default value,
- * it is assumed that the number of
- * entries equals the number of
- * components in the boundary functions
- * and the finite element, and those
- * components in the given boundary
- * function will be used for which the
- * respective flag was set in the
- * component mask.
- *
- * It is assumed that the number of
- * components of the function in @p
- * boundary_function matches that of
- * the finite element used by @p dof.
- *
- * If the finite element used has shape
- * functions that are non-zero in more
- * than one component (in deal.II
- * speak: they are non-primitive), then
- * these components can presently not
- * be used for interpolating boundary
- * values. Thus, the elements in the
- * component mask corresponding to the
- * components of these non-primitive
- * shape functions must be @p false.
- *
- * See the general doc for more
- * information.
- *
- * @ingroup constraints
- */
+ /**
+ * Insert the (algebraic) constraints due
+ * to Dirichlet boundary conditions into
+ * a ConstraintMatrix @p
+ * constraints. This function identifies
+ * the degrees of freedom subject to
+ * Dirichlet boundary conditions, adds
+ * them to the list of constrained DoFs
+ * in @p constraints and sets the
+ * respective inhomogeneity to the value
+ * interpolated around the boundary. If
+ * this routine encounters a DoF that
+ * already is constrained (for instance
+ * by a hanging node constraint, see
+ * below, or any other type of
+ * constraint, e.g. from periodic
+ * boundary conditions), the old setting
+ * of the constraint (dofs the entry is
+ * constrained to, inhomogeneities) is
+ * kept and nothing happens.
+ *
+ * @note When combining adaptively
+ * refined meshes with hanging node
+ * constraints and boundary conditions
+ * like from the current function within
+ * one ConstraintMatrix object, the
+ * hanging node constraints should always
+ * be set first, and then the boundary
+ * conditions since boundary conditions
+ * are not set in the second operation on
+ * degrees of freedom that are already
+ * constrained. This makes sure that the
+ * discretization remains conforming as
+ * is needed. See the discussion on
+ * conflicting constraints in the module
+ * on @ref constraints .
+ *
+ * The parameter @p boundary_component
+ * corresponds to the number @p
+ * boundary_indicator of the face. 255
+ * is an illegal value, since it is
+ * reserved for interior faces.
+ *
+ * The flags in the last parameter, @p
+ * component_mask denote which
+ * components of the finite element
+ * space shall be interpolated. If it
+ * is left as specified by the default
+ * value (i.e. an empty array), all
+ * components are interpolated. If it
+ * is different from the default value,
+ * it is assumed that the number of
+ * entries equals the number of
+ * components in the boundary functions
+ * and the finite element, and those
+ * components in the given boundary
+ * function will be used for which the
+ * respective flag was set in the
+ * component mask.
+ *
+ * It is assumed that the number of
+ * components of the function in @p
+ * boundary_function matches that of
+ * the finite element used by @p dof.
+ *
+ * If the finite element used has shape
+ * functions that are non-zero in more
+ * than one component (in deal.II
+ * speak: they are non-primitive), then
+ * these components can presently not
+ * be used for interpolating boundary
+ * values. Thus, the elements in the
+ * component mask corresponding to the
+ * components of these non-primitive
+ * shape functions must be @p false.
+ *
+ * See the general doc for more
+ * information.
+ *
+ * @ingroup constraints
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const Mapping<DH::dimension,DH::space_dimension> &mapping,
const DH &dof,
ConstraintMatrix &constraints,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * @deprecated This function is there
- * mainly for backward compatibility.
- *
- * Same function as above, but taking
- * only one pair of boundary indicator
- * and corresponding boundary
- * function. Calls the other function
- * with remapped arguments.
- *
- * @ingroup constraints
- */
+ /**
+ * @deprecated This function is there
+ * mainly for backward compatibility.
+ *
+ * Same function as above, but taking
+ * only one pair of boundary indicator
+ * and corresponding boundary
+ * function. Calls the other function
+ * with remapped arguments.
+ *
+ * @ingroup constraints
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const Mapping<DH::dimension,DH::space_dimension> &mapping,
const DH &dof,
ConstraintMatrix &constraints,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Calls the other
- * interpolate_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- *
- * @ingroup constraints
- */
+ /**
+ * Calls the other
+ * interpolate_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ *
+ * @ingroup constraints
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const DH &dof,
const unsigned char boundary_component,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Calls the other
- * interpolate_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- *
- * @ingroup constraints
- */
+ /**
+ * Calls the other
+ * interpolate_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ *
+ * @ingroup constraints
+ */
template <class DH>
- static
+
void
interpolate_boundary_values (const DH &dof,
const typename FunctionMap<DH::space_dimension>::type &function_map,
const std::vector<bool> &component_mask = std::vector<bool>());
- /**
- * Project a function to the boundary
- * of the domain, using the given
- * quadrature formula for the faces. If
- * the @p boundary_values contained
- * values before, the new ones are
- * added, or the old one overwritten if
- * a node of the boundary part to be
- * projected on already was in the
- * variable.
- *
- * If @p component_mapping is empty, it
- * is assumed that the number of
- * components of @p boundary_function
- * matches that of the finite element
- * used by @p dof.
- *
- * In 1d, projection equals
- * interpolation. Therefore,
- * interpolate_boundary_values is
- * called.
- *
- * @arg @p boundary_values: the result
- * of this function, a map containing
- * all indices of degrees of freedom at
- * the boundary (as covered by the
- * boundary parts in @p
- * boundary_functions) and the computed
- * dof value for this degree of
- * freedom.
- *
- * @arg @p component_mapping: if the
- * components in @p boundary_functions
- * and @p dof do not coincide, this
- * vector allows them to be
- * remapped. If the vector is not
- * empty, it has to have one entry for
- * each component in @p dof. This entry
- * is the component number in @p
- * boundary_functions that should be
- * used for this component in @p
- * dof. By default, no remapping is
- * applied.
- */
+ /**
+ * Project a function to the boundary
+ * of the domain, using the given
+ * quadrature formula for the faces. If
+ * the @p boundary_values contained
+ * values before, the new ones are
+ * added, or the old one overwritten if
+ * a node of the boundary part to be
+ * projected on already was in the
+ * variable.
+ *
+ * If @p component_mapping is empty, it
+ * is assumed that the number of
+ * components of @p boundary_function
+ * matches that of the finite element
+ * used by @p dof.
+ *
+ * In 1d, projection equals
+ * interpolation. Therefore,
+ * interpolate_boundary_values is
+ * called.
+ *
+ * @arg @p boundary_values: the result
+ * of this function, a map containing
+ * all indices of degrees of freedom at
+ * the boundary (as covered by the
+ * boundary parts in @p
+ * boundary_functions) and the computed
+ * dof value for this degree of
+ * freedom.
+ *
+ * @arg @p component_mapping: if the
+ * components in @p boundary_functions
+ * and @p dof do not coincide, this
+ * vector allows them to be
+ * remapped. If the vector is not
+ * empty, it has to have one entry for
+ * each component in @p dof. This entry
+ * is the component number in @p
+ * boundary_functions that should be
+ * used for this component in @p
+ * dof. By default, no remapping is
+ * applied.
+ */
template <int dim, int spacedim>
- static void project_boundary_values (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
-
- /**
- * Calls the project_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
+ void project_boundary_values (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
+
+ /**
+ * Calls the project_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
template <int dim, int spacedim>
- static void project_boundary_values (const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_function,
- const Quadrature<dim-1> &q,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
-
- /**
- * Project a function to the boundary of
- * the domain, using the given quadrature
- * formula for the faces. This function
- * identifies the degrees of freedom
- * subject to Dirichlet boundary
- * conditions, adds them to the list of
- * constrained DoFs in @p constraints and
- * sets the respective inhomogeneity to
- * the value resulting from the
- * projection operation. If this routine
- * encounters a DoF that already is
- * constrained (for instance by a hanging
- * node constraint, see below, or any
- * other type of constraint, e.g. from
- * periodic boundary conditions), the old
- * setting of the constraint (dofs the
- * entry is constrained to,
- * inhomogeneities) is kept and nothing
- * happens.
- *
- * @note When combining adaptively
- * refined meshes with hanging node
- * constraints and boundary conditions
- * like from the current function within
- * one ConstraintMatrix object, the
- * hanging node constraints should always
- * be set first, and then the boundary
- * conditions since boundary conditions
- * are not set in the second operation on
- * degrees of freedom that are already
- * constrained. This makes sure that the
- * discretization remains conforming as
- * is needed. See the discussion on
- * conflicting constraints in the module
- * on @ref constraints .
- *
- * If @p component_mapping is empty, it
- * is assumed that the number of
- * components of @p boundary_function
- * matches that of the finite element
- * used by @p dof.
- *
- * In 1d, projection equals
- * interpolation. Therefore,
- * interpolate_boundary_values is
- * called.
- *
- * @arg @p component_mapping: if the
- * components in @p boundary_functions
- * and @p dof do not coincide, this
- * vector allows them to be
- * remapped. If the vector is not
- * empty, it has to have one entry for
- * each component in @p dof. This entry
- * is the component number in @p
- * boundary_functions that should be
- * used for this component in @p
- * dof. By default, no remapping is
- * applied.
- *
- * @ingroup constraints
- */
+ void project_boundary_values (const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_function,
+ const Quadrature<dim-1> &q,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
+
+ /**
+ * Project a function to the boundary of
+ * the domain, using the given quadrature
+ * formula for the faces. This function
+ * identifies the degrees of freedom
+ * subject to Dirichlet boundary
+ * conditions, adds them to the list of
+ * constrained DoFs in @p constraints and
+ * sets the respective inhomogeneity to
+ * the value resulting from the
+ * projection operation. If this routine
+ * encounters a DoF that already is
+ * constrained (for instance by a hanging
+ * node constraint, see below, or any
+ * other type of constraint, e.g. from
+ * periodic boundary conditions), the old
+ * setting of the constraint (dofs the
+ * entry is constrained to,
+ * inhomogeneities) is kept and nothing
+ * happens.
+ *
+ * @note When combining adaptively
+ * refined meshes with hanging node
+ * constraints and boundary conditions
+ * like from the current function within
+ * one ConstraintMatrix object, the
+ * hanging node constraints should always
+ * be set first, and then the boundary
+ * conditions since boundary conditions
+ * are not set in the second operation on
+ * degrees of freedom that are already
+ * constrained. This makes sure that the
+ * discretization remains conforming as
+ * is needed. See the discussion on
+ * conflicting constraints in the module
+ * on @ref constraints .
+ *
+ * If @p component_mapping is empty, it
+ * is assumed that the number of
+ * components of @p boundary_function
+ * matches that of the finite element
+ * used by @p dof.
+ *
+ * In 1d, projection equals
+ * interpolation. Therefore,
+ * interpolate_boundary_values is
+ * called.
+ *
+ * @arg @p component_mapping: if the
+ * components in @p boundary_functions
+ * and @p dof do not coincide, this
+ * vector allows them to be
+ * remapped. If the vector is not
+ * empty, it has to have one entry for
+ * each component in @p dof. This entry
+ * is the component number in @p
+ * boundary_functions that should be
+ * used for this component in @p
+ * dof. By default, no remapping is
+ * applied.
+ *
+ * @ingroup constraints
+ */
template <int dim, int spacedim>
- static void project_boundary_values (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- ConstraintMatrix &constraints,
- std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
-
- /**
- * Calls the project_boundary_values()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- *
- * @ingroup constraints
- */
+ void project_boundary_values (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ ConstraintMatrix &constraints,
+ std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
+
+ /**
+ * Calls the project_boundary_values()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ *
+ * @ingroup constraints
+ */
template <int dim, int spacedim>
- static void project_boundary_values (const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_function,
- const Quadrature<dim-1> &q,
- ConstraintMatrix &constraints,
- std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
-
-
- /**
- * Compute constraints that correspond to
- * boundary conditions of the form
- * $\vec{n}\times\vec{u}=\vec{n}\times\vec{f}$,
- * i.e. the tangential components of $u$
- * and $f$ shall coincide.
- *
- * If the ConstraintMatrix @p constraints
- * contained values or other
- * constraints before, the new ones are
- * added or the old ones overwritten,
- * if a node of the boundary part to be
- * used was already in the list of
- * constraints. This is handled by
- * using inhomogeneous constraints. Please
- * note that when combining adaptive meshes
- * and this kind of constraints, the
- * Dirichlet conditions should be set
- * first, and then completed by hanging
- * node constraints, in order to make sure
- * that the discretization remains
- * consistent. See the discussion on
- * conflicting constraints in the
- * module on @ref constraints .
- *
- * This function is explecitly written to
- * use with the FE_Nedelec elements. Thus
- * it throws an exception, if it is
- * called with other finite elements.
- *
- * The second argument of this function
- * denotes the first vector component in
- * the finite element that corresponds to
- * the vector function that you want to
- * constrain. For example, if we want to
- * solve Maxwell's equations in 3d and the
- * finite element has components
- * $(E_x,E_y,E_z,B_x,B_y,B_z)$ and we want
- * the boundary conditions
- * $\vec{n}\times\vec{B}=\vec{n}\times\vec{f}$,
- * then @p first_vector_component would
- * be 3. Vectors are implicitly assumed to
- * have exactly <code>dim</code> components
- * that are ordered in the same way as we
- * usually order the coordinate directions,
- * i.e. $x$-, $y$-, and finally
- * $z$-component.
- *
- * The parameter @p boundary_component
- * corresponds to the number
- * @p boundary_indicator of the face. 255
- * is an illegal value, since it is
- * reserved for interior faces.
- *
- * The last argument is denoted to compute
- * the normal vector $\vec{n}$ at the
- * boundary points.
- *
- * <h4>Computing constraints</h4>
- *
- * To compute the constraints we use
- * projection-based interpolation as proposed
- * in Solin, Segeth and Dolezel
- * (Higher order finite elements, Chapman&Hall,
- * 2004) on every face located at the
- * boundary.
- *
- * First one projects $\vec{f}$ on the
- * lowest-order edge shape functions. Then the
- * remaining part $(I-P_0)\vec{f}$ of the
- * function is projected on the remaining
- * higher-order edge shape functions. In the
- * last step we project $(I-P_0-P_e)\vec{f}$
- * on the bubble shape functions defined on
- * the face.
- *
- * @ingroup constraints
- */
- template <int dim>
- static void project_boundary_values_curl_conforming (const DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const Mapping<dim>& mapping = StaticMappingQ1<dim>::mapping);
-
- /**
- * Same as above for the hp-namespace.
- *
- * @ingroup constraints
- */
- template <int dim>
- static void project_boundary_values_curl_conforming (const hp::DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const hp::MappingCollection<dim, dim>& mapping_collection = hp::StaticMappingQ1<dim>::mapping_collection);
-
-
- /**
- * Compute constraints that correspond to
- * boundary conditions of the form
- * $\vec{n}^T\vec{u}=\vec{n}^T\vec{f}$,
- * i.e. the normal components of $u$
- * and $f$ shall coincide.
- *
- * If the ConstraintMatrix @p constraints
- * contained values or other
- * constraints before, the new ones are
- * added or the old ones overwritten,
- * if a node of the boundary part to be
- * used was already in the list of
- * constraints. This is handled by
- * using inhomogeneous constraints. Please
- * note that when combining adaptive meshes
- * and this kind of constraints, the
- * Dirichlet conditions should be set
- * first, and then completed by hanging
- * node constraints, in order to make sure
- * that the discretization remains
- * consistent. See the discussion on
- * conflicting constraints in the
- * module on @ref constraints .
- *
- * This function is explecitly written to
- * use with the FE_RaviartThomas elements.
- * Thus it throws an exception, if it is
- * called with other finite elements.
- *
- * The second argument of this function
- * denotes the first vector component in
- * the finite element that corresponds to
- * the vector function that you want to
- * constrain. Vectors are implicitly
- * assumed to have exactly
- * <code>dim</code> components that are
- * ordered in the same way as we
- * usually order the coordinate directions,
- * i.e. $x$-, $y$-, and finally
- * $z$-component.
- *
- * The parameter @p boundary_component
- * corresponds to the number
- * @p boundary_indicator of the face. 255
- * is an illegal value, since it is
- * reserved for interior faces.
- *
- * The last argument is denoted to compute
- * the normal vector $\vec{n}$ at the
- * boundary points.
- *
- * <h4>Computing constraints</h4>
- *
- * To compute the constraints we use
- * interpolation operator proposed
- * in Brezzi, Fortin (Mixed and Hybrid
- * (Finite Element Methods, Springer,
- * 1991) on every face located at the
- * boundary.
- *
- * @ingroup constraints
- */
- template<int dim>
- static void project_boundary_values_div_conforming (const DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const Mapping<dim>& mapping = StaticMappingQ1<dim>::mapping);
-
- /**
- * Same as above for the hp-namespace.
- *
- * @ingroup constraints
- */
- template<int dim>
- static void project_boundary_values_div_conforming (const hp::DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const hp::MappingCollection<dim, dim>& mapping_collection = hp::StaticMappingQ1<dim>::mapping_collection);
-
-
- /**
- * Compute the constraints that
- * correspond to boundary conditions of
- * the form $\vec n \cdot \vec u=0$,
- * i.e. no normal flux if $\vec u$ is a
- * vector-valued quantity. These
- * conditions have exactly the form
- * handled by the ConstraintMatrix class,
- * so instead of creating a map between
- * boundary degrees of freedom and
- * corresponding value, we here create a
- * list of constraints that are written
- * into a ConstraintMatrix. This object
- * may already have some content, for
- * example from hanging node constraints,
- * that remains untouched. These
- * constraints have to be applied to the
- * linear system like any other such
- * constraints, i.e. you have to condense
- * the linear system with the constraints
- * before solving, and you have to
- * distribute the solution vector
- * afterwards.
- *
- * The use of this function is
- * explained in more detail in
- * step-31. It
- * doesn't make much sense in 1d,
- * so the function throws an
- * exception in that case.
- *
- * The second argument of this
- * function denotes the first
- * vector component in the finite
- * element that corresponds to
- * the vector function that you
- * want to constrain. For
- * example, if we were solving a
- * Stokes equation in 2d and the
- * finite element had components
- * $(u,v,p)$, then @p
- * first_vector_component would
- * be zero. On the other hand, if
- * we solved the Maxwell
- * equations in 3d and the finite
- * element has components
- * $(E_x,E_y,E_z,B_x,B_y,B_z)$
- * and we want the boundary
- * condition $\vec n\cdot \vec
- * B=0$, then @p
- * first_vector_component would
- * be 3. Vectors are implicitly
- * assumed to have exactly
- * <code>dim</code> components
- * that are ordered in the same
- * way as we usually order the
- * coordinate directions,
- * i.e. $x$-, $y$-, and finally
- * $z$-component. The function
- * assumes, but can't check, that
- * the vector components in the
- * range
- * <code>[first_vector_component,first_vector_component+dim)</code>
- * come from the same base finite
- * element. For example, in the
- * Stokes example above, it would
- * not make sense to use a
- * <code>FESystem@<dim@>(FE_Q@<dim@>(2),
- * 1, FE_Q@<dim@>(1), dim)</code>
- * (note that the first velocity
- * vector component is a $Q_2$
- * element, whereas all the other
- * ones are $Q_1$ elements) as
- * there would be points on the
- * boundary where the
- * $x$-velocity is defined but no
- * corresponding $y$- or
- * $z$-velocities.
- *
- * The third argument denotes the set of
- * boundary indicators on which the
- * boundary condition is to be
- * enforced. Note that, as explained
- * below, this is one of the few
- * functions where it makes a difference
- * where we call the function multiple
- * times with only one boundary
- * indicator, or whether we call the
- * function onces with the whole set of
- * boundary indicators at once.
- *
- * The mapping argument is used to
- * compute the boundary points where the function
- * needs to request the normal vector $\vec n$
- * from the boundary description.
- *
- * @note When combining adaptively
- * refined meshes with hanging node
- * constraints and boundary conditions
- * like from the current function within
- * one ConstraintMatrix object, the
- * hanging node constraints should always
- * be set first, and then the boundary
- * conditions since boundary conditions
- * are not set in the second operation on
- * degrees of freedom that are already
- * constrained. This makes sure that the
- * discretization remains conforming as
- * is needed. See the discussion on
- * conflicting constraints in the module
- * on @ref constraints .
- *
- *
- * <h4>Computing constraints in 2d</h4>
- *
- * Computing these constraints requires
- * some smarts. The main question
- * revolves around the question what the
- * normal vector is. Consider the
- * following situation:
- * <p ALIGN="center">
- * @image html no_normal_flux_1.png
- * </p>
- *
- * Here, we have two cells that use a
- * bilinear mapping
- * (i.e. MappingQ1). Consequently, for
- * each of the cells, the normal vector
- * is perpendicular to the straight
- * edge. If the two edges at the top and
- * right are meant to approximate a
- * curved boundary (as indicated by the
- * dashed line), then neither of the two
- * computed normal vectors are equal to
- * the exact normal vector (though they
- * approximate it as the mesh is refined
- * further). What is worse, if we
- * constrain $\vec n \cdot \vec u=0$ at
- * the common vertex with the normal
- * vector from both cells, then we
- * constrain the vector $\vec u$ with
- * respect to two linearly independent
- * vectors; consequently, the constraint
- * would be $\vec u=0$ at this point
- * (i.e. <i>all</i> components of the
- * vector), which is not what we wanted.
- *
- * To deal with this situation, the
- * algorithm works in the following way:
- * at each point where we want to
- * constrain $\vec u$, we first collect
- * all normal vectors that adjacent cells
- * might compute at this point. We then
- * do not constrain $\vec n \cdot \vec
- * u=0$ for <i>each</i> of these normal
- * vectors but only for the
- * <i>average</i> of the normal
- * vectors. In the example above, we
- * therefore record only a single
- * constraint $\vec n \cdot \vec {\bar
- * u}=0$, where $\vec {\bar u}$ is the
- * average of the two indicated normal
- * vectors.
- *
- * Unfortunately, this is not quite
- * enough. Consider the situation here:
- *
- * <p ALIGN="center">
- * @image html no_normal_flux_2.png
- * </p>
- *
- * If again the top and right edges
- * approximate a curved boundary, and the
- * left boundary a separate boundary (for
- * example straight) so that the exact
- * boundary has indeed a corner at the
- * top left vertex, then the above
- * construction would not work: here, we
- * indeed want the constraint that $\vec
- * u$ at this point (because the normal
- * velocities with respect to both the
- * left normal as well as the top normal
- * vector should be zero), not that the
- * velocity in the direction of the
- * average normal vector is zero.
- *
- * Consequently, we use the following
- * heuristic to determine whether all
- * normal vectors computed at one point
- * are to be averaged: if two normal
- * vectors for the same point are
- * computed on <i>different</i> cells,
- * then they are to be averaged. This
- * covers the first example above. If
- * they are computed from the same cell,
- * then the fact that they are different
- * is considered indication that they
- * come from different parts of the
- * boundary that might be joined by a
- * real corner, and must not be averaged.
- *
- * There is one problem with this
- * scheme. If, for example, the same
- * domain we have considered above, is
- * discretized with the following mesh,
- * then we get into trouble:
- *
- * <p ALIGN="center">
- * @image html no_normal_flux_2.png
- * </p>
- *
- * Here, the algorithm assumes that the
- * boundary does not have a corner at the
- * point where faces $F1$ and $F2$ join
- * because at that point there are two
- * different normal vectors computed from
- * different cells. If you intend for
- * there to be a corner of the exact
- * boundary at this point, the only way
- * to deal with this is to assign the two
- * parts of the boundary different
- * boundary indicators and call this
- * function twice, once for each boundary
- * indicators; doing so will yield only
- * one normal vector at this point per
- * invocation (because we consider only
- * one boundary part at a time), with the
- * result that the normal vectors will
- * not be averaged.
- *
- *
- * <h4>Computing constraints in 3d</h4>
- *
- * The situation is more
- * complicated in 3d. Consider
- * the following case where we
- * want to compute the
- * constraints at the marked
- * vertex:
- *
- * <p ALIGN="center">
- * @image html no_normal_flux_4.png
- * </p>
- *
- * Here, we get four different
- * normal vectors, one from each
- * of the four faces that meet at
- * the vertex. Even though they
- * may form a complete set of
- * vectors, it is not our intent
- * to constrain all components of
- * the vector field at this
- * point. Rather, we would like
- * to still allow tangential
- * flow, where the term
- * "tangential" has to be
- * suitably defined.
- *
- * In a case like this, the
- * algorithm proceeds as follows:
- * for each cell that has
- * computed two tangential
- * vectors at this point, we
- * compute the unconstrained
- * direction as the outer product
- * of the two tangential vectors
- * (if necessary multiplied by
- * minus one). We then average
- * these tangential
- * vectors. Finally, we compute
- * constraints for the two
- * directions perpendicular to
- * this averaged tangential
- * direction.
- *
- * There are cases where one cell
- * contributes two tangential
- * directions and another one
- * only one; for example, this
- * would happen if both top and
- * front faces of the left cell
- * belong to the boundary
- * selected whereas only the top
- * face of the right cell belongs
- * to it. This case is not
- * currently implemented.
- *
- *
- * <h4>Results</h4>
- *
- * Because it makes for good
- * pictures, here are two images
- * of vector fields on a circle
- * and on a sphere to which the
- * constraints computed by this
- * function have been applied:
- *
- * <p ALIGN="center">
- * @image html no_normal_flux_5.png
- * @image html no_normal_flux_6.png
- * </p>
- *
- * The vectors fields are not
- * physically reasonable but the
- * tangentiality constraint is
- * clearly enforced. The fact
- * that the vector fields are
- * zero at some points on the
- * boundary is an artifact of the
- * way it is created, it is not
- * constrained to be zero at
- * these points.
- *
- * @ingroup constraints
- */
+ void project_boundary_values (const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_function,
+ const Quadrature<dim-1> &q,
+ ConstraintMatrix &constraints,
+ std::vector<unsigned int> component_mapping = std::vector<unsigned int>());
+
+
+ /**
+ * Compute constraints that correspond to
+ * boundary conditions of the form
+ * $\vec{n}\times\vec{u}=\vec{n}\times\vec{f}$,
+ * i.e. the tangential components of $u$
+ * and $f$ shall coincide.
+ *
+ * If the ConstraintMatrix @p constraints
+ * contained values or other
+ * constraints before, the new ones are
+ * added or the old ones overwritten,
+ * if a node of the boundary part to be
+ * used was already in the list of
+ * constraints. This is handled by
+ * using inhomogeneous constraints. Please
+ * note that when combining adaptive meshes
+ * and this kind of constraints, the
+ * Dirichlet conditions should be set
+ * first, and then completed by hanging
+ * node constraints, in order to make sure
+ * that the discretization remains
+ * consistent. See the discussion on
+ * conflicting constraints in the
+ * module on @ref constraints .
+ *
+ * This function is explecitly written to
+ * use with the FE_Nedelec elements. Thus
+ * it throws an exception, if it is
+ * called with other finite elements.
+ *
+ * The second argument of this function
+ * denotes the first vector component in
+ * the finite element that corresponds to
+ * the vector function that you want to
+ * constrain. For example, if we want to
+ * solve Maxwell's equations in 3d and the
+ * finite element has components
+ * $(E_x,E_y,E_z,B_x,B_y,B_z)$ and we want
+ * the boundary conditions
+ * $\vec{n}\times\vec{B}=\vec{n}\times\vec{f}$,
+ * then @p first_vector_component would
+ * be 3. Vectors are implicitly assumed to
+ * have exactly <code>dim</code> components
+ * that are ordered in the same way as we
+ * usually order the coordinate directions,
+ * i.e. $x$-, $y$-, and finally
+ * $z$-component.
+ *
+ * The parameter @p boundary_component
+ * corresponds to the number
+ * @p boundary_indicator of the face. 255
+ * is an illegal value, since it is
+ * reserved for interior faces.
+ *
+ * The last argument is denoted to compute
+ * the normal vector $\vec{n}$ at the
+ * boundary points.
+ *
+ * <h4>Computing constraints</h4>
+ *
+ * To compute the constraints we use
+ * projection-based interpolation as proposed
+ * in Solin, Segeth and Dolezel
+ * (Higher order finite elements, Chapman&Hall,
+ * 2004) on every face located at the
+ * boundary.
+ *
+ * First one projects $\vec{f}$ on the
+ * lowest-order edge shape functions. Then the
+ * remaining part $(I-P_0)\vec{f}$ of the
+ * function is projected on the remaining
+ * higher-order edge shape functions. In the
+ * last step we project $(I-P_0-P_e)\vec{f}$
+ * on the bubble shape functions defined on
+ * the face.
+ *
+ * @ingroup constraints
+ */
+ template <int dim>
+ void project_boundary_values_curl_conforming (const DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const Mapping<dim>& mapping = MappingQ1<dim>::mapping);
+
+ /**
+ * Same as above for the hp-namespace.
+ *
+ * @ingroup constraints
+ */
+ template <int dim>
+ void project_boundary_values_curl_conforming (const hp::DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const hp::MappingCollection<dim, dim>& mapping_collection = hp::StaticMappingQ1<dim>::mapping_collection);
+
+
+ /**
+ * Compute constraints that correspond to
+ * boundary conditions of the form
+ * $\vec{n}^T\vec{u}=\vec{n}^T\vec{f}$,
+ * i.e. the normal components of $u$
+ * and $f$ shall coincide.
+ *
+ * If the ConstraintMatrix @p constraints
+ * contained values or other
+ * constraints before, the new ones are
+ * added or the old ones overwritten,
+ * if a node of the boundary part to be
+ * used was already in the list of
+ * constraints. This is handled by
+ * using inhomogeneous constraints. Please
+ * note that when combining adaptive meshes
+ * and this kind of constraints, the
+ * Dirichlet conditions should be set
+ * first, and then completed by hanging
+ * node constraints, in order to make sure
+ * that the discretization remains
+ * consistent. See the discussion on
+ * conflicting constraints in the
+ * module on @ref constraints .
+ *
+ * This function is explecitly written to
+ * use with the FE_RaviartThomas elements.
+ * Thus it throws an exception, if it is
+ * called with other finite elements.
+ *
+ * The second argument of this function
+ * denotes the first vector component in
+ * the finite element that corresponds to
+ * the vector function that you want to
+ * constrain. Vectors are implicitly
+ * assumed to have exactly
+ * <code>dim</code> components that are
+ * ordered in the same way as we
+ * usually order the coordinate directions,
+ * i.e. $x$-, $y$-, and finally
+ * $z$-component.
+ *
+ * The parameter @p boundary_component
+ * corresponds to the number
+ * @p boundary_indicator of the face. 255
+ * is an illegal value, since it is
+ * reserved for interior faces.
+ *
+ * The last argument is denoted to compute
+ * the normal vector $\vec{n}$ at the
+ * boundary points.
+ *
+ * <h4>Computing constraints</h4>
+ *
+ * To compute the constraints we use
+ * interpolation operator proposed
+ * in Brezzi, Fortin (Mixed and Hybrid
+ * (Finite Element Methods, Springer,
+ * 1991) on every face located at the
+ * boundary.
+ *
+ * @ingroup constraints
+ */
+ template<int dim>
+ void project_boundary_values_div_conforming (const DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const Mapping<dim>& mapping = MappingQ1<dim>::mapping);
+
+ /**
+ * Same as above for the hp-namespace.
+ *
+ * @ingroup constraints
+ */
+ template<int dim>
+ void project_boundary_values_div_conforming (const hp::DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const hp::MappingCollection<dim, dim>& mapping_collection = hp::StaticMappingQ1<dim>::mapping_collection);
+
+
+ /**
+ * Compute the constraints that
+ * correspond to boundary conditions of
+ * the form $\vec n \cdot \vec u=0$,
+ * i.e. no normal flux if $\vec u$ is a
+ * vector-valued quantity. These
+ * conditions have exactly the form
+ * handled by the ConstraintMatrix class,
+ * so instead of creating a map between
+ * boundary degrees of freedom and
+ * corresponding value, we here create a
+ * list of constraints that are written
+ * into a ConstraintMatrix. This object
+ * may already have some content, for
+ * example from hanging node constraints,
+ * that remains untouched. These
+ * constraints have to be applied to the
+ * linear system like any other such
+ * constraints, i.e. you have to condense
+ * the linear system with the constraints
+ * before solving, and you have to
+ * distribute the solution vector
+ * afterwards.
+ *
+ * The use of this function is
+ * explained in more detail in
+ * step-31. It
+ * doesn't make much sense in 1d,
+ * so the function throws an
+ * exception in that case.
+ *
+ * The second argument of this
+ * function denotes the first
+ * vector component in the finite
+ * element that corresponds to
+ * the vector function that you
+ * want to constrain. For
+ * example, if we were solving a
+ * Stokes equation in 2d and the
+ * finite element had components
+ * $(u,v,p)$, then @p
+ * first_vector_component would
+ * be zero. On the other hand, if
+ * we solved the Maxwell
+ * equations in 3d and the finite
+ * element has components
+ * $(E_x,E_y,E_z,B_x,B_y,B_z)$
+ * and we want the boundary
+ * condition $\vec n\cdot \vec
+ * B=0$, then @p
+ * first_vector_component would
+ * be 3. Vectors are implicitly
+ * assumed to have exactly
+ * <code>dim</code> components
+ * that are ordered in the same
+ * way as we usually order the
+ * coordinate directions,
+ * i.e. $x$-, $y$-, and finally
+ * $z$-component. The function
+ * assumes, but can't check, that
+ * the vector components in the
+ * range
+ * <code>[first_vector_component,first_vector_component+dim)</code>
+ * come from the same base finite
+ * element. For example, in the
+ * Stokes example above, it would
+ * not make sense to use a
+ * <code>FESystem@<dim@>(FE_Q@<dim@>(2),
+ * 1, FE_Q@<dim@>(1), dim)</code>
+ * (note that the first velocity
+ * vector component is a $Q_2$
+ * element, whereas all the other
+ * ones are $Q_1$ elements) as
+ * there would be points on the
+ * boundary where the
+ * $x$-velocity is defined but no
+ * corresponding $y$- or
+ * $z$-velocities.
+ *
+ * The third argument denotes the set of
+ * boundary indicators on which the
+ * boundary condition is to be
+ * enforced. Note that, as explained
+ * below, this is one of the few
+ * functions where it makes a difference
+ * where we call the function multiple
+ * times with only one boundary
+ * indicator, or whether we call the
+ * function onces with the whole set of
+ * boundary indicators at once.
+ *
+ * The mapping argument is used to
+ * compute the boundary points where the function
+ * needs to request the normal vector $\vec n$
+ * from the boundary description.
+ *
+ * @note When combining adaptively
+ * refined meshes with hanging node
+ * constraints and boundary conditions
+ * like from the current function within
+ * one ConstraintMatrix object, the
+ * hanging node constraints should always
+ * be set first, and then the boundary
+ * conditions since boundary conditions
+ * are not set in the second operation on
+ * degrees of freedom that are already
+ * constrained. This makes sure that the
+ * discretization remains conforming as
+ * is needed. See the discussion on
+ * conflicting constraints in the module
+ * on @ref constraints .
+ *
+ *
+ * <h4>Computing constraints in 2d</h4>
+ *
+ * Computing these constraints requires
+ * some smarts. The main question
+ * revolves around the question what the
+ * normal vector is. Consider the
+ * following situation:
+ * <p ALIGN="center">
+ * @image html no_normal_flux_1.png
+ * </p>
+ *
+ * Here, we have two cells that use a
+ * bilinear mapping
+ * (i.e. MappingQ1). Consequently, for
+ * each of the cells, the normal vector
+ * is perpendicular to the straight
+ * edge. If the two edges at the top and
+ * right are meant to approximate a
+ * curved boundary (as indicated by the
+ * dashed line), then neither of the two
+ * computed normal vectors are equal to
+ * the exact normal vector (though they
+ * approximate it as the mesh is refined
+ * further). What is worse, if we
+ * constrain $\vec n \cdot \vec u=0$ at
+ * the common vertex with the normal
+ * vector from both cells, then we
+ * constrain the vector $\vec u$ with
+ * respect to two linearly independent
+ * vectors; consequently, the constraint
+ * would be $\vec u=0$ at this point
+ * (i.e. <i>all</i> components of the
+ * vector), which is not what we wanted.
+ *
+ * To deal with this situation, the
+ * algorithm works in the following way:
+ * at each point where we want to
+ * constrain $\vec u$, we first collect
+ * all normal vectors that adjacent cells
+ * might compute at this point. We then
+ * do not constrain $\vec n \cdot \vec
+ * u=0$ for <i>each</i> of these normal
+ * vectors but only for the
+ * <i>average</i> of the normal
+ * vectors. In the example above, we
+ * therefore record only a single
+ * constraint $\vec n \cdot \vec {\bar
+ * u}=0$, where $\vec {\bar u}$ is the
+ * average of the two indicated normal
+ * vectors.
+ *
+ * Unfortunately, this is not quite
+ * enough. Consider the situation here:
+ *
+ * <p ALIGN="center">
+ * @image html no_normal_flux_2.png
+ * </p>
+ *
+ * If again the top and right edges
+ * approximate a curved boundary, and the
+ * left boundary a separate boundary (for
+ * example straight) so that the exact
+ * boundary has indeed a corner at the
+ * top left vertex, then the above
+ * construction would not work: here, we
+ * indeed want the constraint that $\vec
+ * u$ at this point (because the normal
+ * velocities with respect to both the
+ * left normal as well as the top normal
+ * vector should be zero), not that the
+ * velocity in the direction of the
+ * average normal vector is zero.
+ *
+ * Consequently, we use the following
+ * heuristic to determine whether all
+ * normal vectors computed at one point
+ * are to be averaged: if two normal
+ * vectors for the same point are
+ * computed on <i>different</i> cells,
+ * then they are to be averaged. This
+ * covers the first example above. If
+ * they are computed from the same cell,
+ * then the fact that they are different
+ * is considered indication that they
+ * come from different parts of the
+ * boundary that might be joined by a
+ * real corner, and must not be averaged.
+ *
+ * There is one problem with this
+ * scheme. If, for example, the same
+ * domain we have considered above, is
+ * discretized with the following mesh,
+ * then we get into trouble:
+ *
+ * <p ALIGN="center">
+ * @image html no_normal_flux_2.png
+ * </p>
+ *
+ * Here, the algorithm assumes that the
+ * boundary does not have a corner at the
+ * point where faces $F1$ and $F2$ join
+ * because at that point there are two
+ * different normal vectors computed from
+ * different cells. If you intend for
+ * there to be a corner of the exact
+ * boundary at this point, the only way
+ * to deal with this is to assign the two
+ * parts of the boundary different
+ * boundary indicators and call this
+ * function twice, once for each boundary
+ * indicators; doing so will yield only
+ * one normal vector at this point per
+ * invocation (because we consider only
+ * one boundary part at a time), with the
+ * result that the normal vectors will
+ * not be averaged.
+ *
+ *
+ * <h4>Computing constraints in 3d</h4>
+ *
+ * The situation is more
+ * complicated in 3d. Consider
+ * the following case where we
+ * want to compute the
+ * constraints at the marked
+ * vertex:
+ *
+ * <p ALIGN="center">
+ * @image html no_normal_flux_4.png
+ * </p>
+ *
+ * Here, we get four different
+ * normal vectors, one from each
+ * of the four faces that meet at
+ * the vertex. Even though they
+ * may form a complete set of
+ * vectors, it is not our intent
+ * to constrain all components of
+ * the vector field at this
+ * point. Rather, we would like
+ * to still allow tangential
+ * flow, where the term
+ * "tangential" has to be
+ * suitably defined.
+ *
+ * In a case like this, the
+ * algorithm proceeds as follows:
+ * for each cell that has
+ * computed two tangential
+ * vectors at this point, we
+ * compute the unconstrained
+ * direction as the outer product
+ * of the two tangential vectors
+ * (if necessary multiplied by
+ * minus one). We then average
+ * these tangential
+ * vectors. Finally, we compute
+ * constraints for the two
+ * directions perpendicular to
+ * this averaged tangential
+ * direction.
+ *
+ * There are cases where one cell
+ * contributes two tangential
+ * directions and another one
+ * only one; for example, this
+ * would happen if both top and
+ * front faces of the left cell
+ * belong to the boundary
+ * selected whereas only the top
+ * face of the right cell belongs
+ * to it. This case is not
+ * currently implemented.
+ *
+ *
+ * <h4>Results</h4>
+ *
+ * Because it makes for good
+ * pictures, here are two images
+ * of vector fields on a circle
+ * and on a sphere to which the
+ * constraints computed by this
+ * function have been applied:
+ *
+ * <p ALIGN="center">
+ * @image html no_normal_flux_5.png
+ * @image html no_normal_flux_6.png
+ * </p>
+ *
+ * The vectors fields are not
+ * physically reasonable but the
+ * tangentiality constraint is
+ * clearly enforced. The fact
+ * that the vector fields are
+ * zero at some points on the
+ * boundary is an artifact of the
+ * way it is created, it is not
+ * constrained to be zero at
+ * these points.
+ *
+ * @ingroup constraints
+ */
template <int dim, template <int, int> class DH, int spacedim>
- static
+
void
compute_no_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
const unsigned int first_vector_component,
const std::set<unsigned char> &boundary_ids,
ConstraintMatrix &constraints,
- const Mapping<dim, spacedim> &mapping = StaticMappingQ1<dim>::mapping);
-
-
- //@}
- /**
- * @name Assembling of right hand sides
- */
- //@{
-
- /**
- * Create a right hand side
- * vector. Prior content of the
- * given @p rhs_vector vector is
- * deleted.
- *
- * See the general documentation of this
- * class for further information.
- */
- template <int dim, int spacedim>
- static void create_right_hand_side (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector);
-
- /**
- * Calls the create_right_hand_side()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, int spacedim>
- static void create_right_hand_side (const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector);
-
- /**
- * Like the previous set of functions,
- * but for hp objects.
- */
- template <int dim, int spacedim>
- static void create_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof,
- const hp::QCollection<dim> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector);
-
- /**
- * Like the previous set of functions,
- * but for hp objects.
- */
- template <int dim, int spacedim>
- static void create_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof,
- const hp::QCollection<dim> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector);
-
- /**
- * Create a right hand side
- * vector for a point source at point @p p.
- * Prior content of the
- * given @p rhs_vector vector is
- * deleted.
- *
- * See the general documentation of this
- * class for further information.
- */
- template <int dim, int spacedim>
- static void create_point_source_vector(const Mapping<dim,spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector);
-
- /**
- * Calls the create_point_source_vector()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, int spacedim>
- static void create_point_source_vector(const DoFHandler<dim,spacedim> &dof,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector);
-
- /**
- * Like the previous set of functions,
- * but for hp objects.
- */
- template <int dim, int spacedim>
- static void create_point_source_vector(const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector);
-
- /**
- * Like the previous set of functions,
- * but for hp objects. The function uses
- * the default Q1 mapping object. Note
- * that if your hp::DoFHandler uses any
- * active fe index other than zero, then
- * you need to call the function above
- * that provides a mapping object for
- * each active fe index.
- */
- template <int dim, int spacedim>
- static void create_point_source_vector(const hp::DoFHandler<dim,spacedim> &dof,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector);
-
- /**
- * Create a right hand side
- * vector from boundary
- * forces. Prior content of the
- * given @p rhs_vector vector is
- * deleted.
- *
- * See the general documentation of this
- * class for further information.
- */
- template <int dim, int spacedim>
- static void create_boundary_right_hand_side (const Mapping<dim,spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim-1> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
-
- /**
- * Calls the
- * create_boundary_right_hand_side()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, int spacedim>
- static void create_boundary_right_hand_side (const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim-1> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
-
- /**
- * Same as the set of functions above,
- * but for hp objects.
- */
- template <int dim, int spacedim>
- static void create_boundary_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof,
- const hp::QCollection<dim-1> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
-
- /**
- * Calls the
- * create_boundary_right_hand_side()
- * function, see above, with a
- * single Q1 mapping as
- * collection. This function
- * therefore will only work if
- * the only active fe index in
- * use is zero.
- */
- template <int dim, int spacedim>
- static void create_boundary_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof,
- const hp::QCollection<dim-1> &q,
- const Function<spacedim> &rhs,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
-
- //@}
- /**
- * @name Evaluation of functions
- * and errors
- */
- //@{
-
- /**
- * Compute the error of the
- * finite element solution.
- * Integrate the difference
- * between a reference function
- * which is given as a continuous
- * function object, and a finite
- * element function.
- *
- * The value of @p exponent is
- * used for computing $L^p$-norms
- * and $W^{1,p}$-norms.
- *
- * The additional argument @p
- * weight allows to evaluate
- * weighted norms. The weight
- * function may be scalar,
- * establishing a weight in the
- * domain for all components
- * equally. This may be used, for
- * instance, to only integrates
- * over parts of the domain.
- *
- * The weight function may also
- * be vector-valued, with as many
- * components as the finite
- * element function: Then,
- * different components get
- * different weights. A typical
- * application is when the error
- * with respect to only one or a
- * subset of the solution
- * variables is to be computed,
- * in which the other components
- * would have weight values equal
- * to zero. The
- * ComponentSelectFunction class
- * is particularly useful for
- * this purpose.
- *
- * The weight function is
- * expected to be positive, but
- * negative values are not
- * filtered. By default, no
- * weighting function is given,
- * i.e. weight=1 in the whole
- * domain for all vector
- * components uniformly.
- *
- * It is assumed that the number
- * of components of the function
- * @p exact_solution matches that
- * of the finite element used by
- * @p dof.
- *
- * See the general documentation of this
- * class for more information.
- *
- * @note Instantiations for this template
- * are provided for some vector types
- * (see the general documentation of the
- * class), but only for InVectors as in
- * the documentation of the class,
- * OutVector only Vector<double> and
- * Vector<float>.
- */
- template <int dim, class InVector, class OutVector, int spacedim>
- static void integrate_difference (const Mapping<dim,spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const Quadrature<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight=0,
- const double exponent = 2.);
-
- /**
- * Calls the integrate_difference()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, class InVector, class OutVector, int spacedim>
- static void integrate_difference (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const Quadrature<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight=0,
- const double exponent = 2.);
-
- template <int dim, class InVector, class OutVector, int spacedim>
- static void integrate_difference (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const hp::QCollection<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight=0,
- const double exponent = 2.);
-
- /**
- * Calls the integrate_difference()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, class InVector, class OutVector, int spacedim>
- static void integrate_difference (const hp::DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const hp::QCollection<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight=0,
- const double exponent = 2.);
-
- /**
- * Point error evaluation. Find
- * the first cell containing the
- * given point and compute the
- * difference of a (possibly
- * vector-valued) finite element
- * function and a continuous
- * function (with as many vector
- * components as the finite
- * element) at this point.
- *
- * This is a wrapper function
- * using a Q1-mapping for cell
- * boundaries to call the other
- * point_difference() function.
- */
- template <int dim, class InVector, int spacedim>
- static void point_difference (const DoFHandler<dim,spacedim>& dof,
- const InVector& fe_function,
- const Function<spacedim>& exact_solution,
- Vector<double>& difference,
- const Point<spacedim>& point);
-
- /**
- * Point error evaluation. Find
- * the first cell containing the
- * given point and compute the
- * difference of a (possibly
- * vector-valued) finite element
- * function and a continuous
- * function (with as many vector
- * components as the finite
- * element) at this point.
- *
- * Compared with the other
- * function of the same name,
- * this function uses an
- * arbitrary mapping to evaluate
- * the difference.
- */
- template <int dim, class InVector, int spacedim>
- static void point_difference (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim>& dof,
- const InVector& fe_function,
- const Function<spacedim>& exact_solution,
- Vector<double>& difference,
- const Point<spacedim>& point);
-
- /**
- * Evaluate a possibly
- * vector-valued finite element
- * function defined by the given
- * DoFHandler and nodal vector at
- * the given point, and return
- * the (vector) value of this
- * function through the last
- * argument.
- *
- * This is a wrapper function
- * using a Q1-mapping for cell
- * boundaries to call the other
- * point_difference() function.
- */
- template <int dim, class InVector, int spacedim>
- static
- void
- point_value (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point,
- Vector<double> &value);
-
- /**
- * Evaluate a scalar finite
- * element function defined by
- * the given DoFHandler and nodal
- * vector at the given point, and
- * return the value of this
- * function.
- *
- * Compared with the other
- * function of the same name,
- * this is a wrapper function using
- * a Q1-mapping for cells.
- *
- * This function is used in the
- * "Possibilities for extensions" part of
- * the results section of @ref step_3
- * "step-3".
- */
- template <int dim, class InVector, int spacedim>
- static
- double
- point_value (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point);
-
- /**
- * Evaluate a possibly
- * vector-valued finite element
- * function defined by the given
- * DoFHandler and nodal vector at
- * the given point, and return
- * the (vector) value of this
- * function through the last
- * argument.
- *
- * Compared with the other
- * function of the same name,
- * this function uses an arbitrary
- * mapping to evaluate the difference.
- */
- template <int dim, class InVector, int spacedim>
- static
- void
- point_value (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point,
- Vector<double> &value);
-
- /**
- * Evaluate a scalar finite
- * element function defined by
- * the given DoFHandler and nodal
- * vector at the given point, and
- * return the value of this
- * function.
- *
- * Compared with the other
- * function of the same name,
- * this function uses an arbitrary
- * mapping to evaluate the difference.
- */
- template <int dim, class InVector, int spacedim>
- static
- double
- point_value (const Mapping<dim,spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point);
-
- //@}
- /**
- * Mean value operations
- */
- //@{
-
- /**
- * Subtract the (algebraic) mean value
- * from a vector. This function is most
- * frequently used as a mean-value filter
- * for Stokes: The pressure in Stokes'
- * equations with only Dirichlet
- * boundaries for the velocities is only
- * determined up to a constant. This
- * function allows to subtract the mean
- * value of the pressure. It is usually
- * called in a preconditioner and
- * generates updates with mean value
- * zero. The mean value is computed as
- * the mean value of the degrees of
- * freedom values as given by the input
- * vector; they are not weighted by the
- * area of cells, i.e. the mean is
- * computed as $\sum_i v_i$, rather than
- * as $\int_\Omega v(x) = \int_\Omega
- * \sum_i v_i \phi_i(x)$. The latter can
- * be obtained from the
- * VectorTools::compute_mean_function,
- * however.
- *
- * Apart from the vector @p v to operate
- * on, this function takes a boolean mask
- * that has a true entry for
- * every component for which the mean
- * value shall be computed and later
- * subtracted. The argument is used to
- * denote which components of the
- * solution vector correspond to the
- * pressure, and avoid touching all other
- * components of the vector, such as the
- * velocity components.
- *
- * @note In the context of using this
- * function to filter out the kernel of
- * an operator (such as the null space of
- * the Stokes operator that consists of
- * the constant pressures), this function
- * only makes sense for finite elements
- * for which the null space indeed
- * consists of the vector
- * $(1,1,\ldots,1)^T$. This is the case
- * for example for the usual Lagrange
- * elements where the sum of all shape
- * functions equals the function that is
- * constant one. However, it is not true
- * for some other functions: for example,
- * for the FE_DGP element (another valid
- * choice for the pressure in Stokes
- * discretizations), the first shape
- * function on each cell is constant
- * while further elements are $L_2$
- * orthogonal to it (on the reference
- * cell); consequently, the sum of all
- * shape functions is not equal to one,
- * and the vector that is associated with
- * the constant mode is not equal to
- * $(1,1,\ldots,1)^T$. For such elements,
- * a different procedure has to be used
- * when subtracting the mean value.
- */
- static void subtract_mean_value(Vector<double> &v,
- const std::vector<bool> &p_select);
-
- /**
- * Compute the mean value of one
- * component of the solution.
- *
- * This function integrates the
- * chosen component over the
- * whole domain and returns the
- * result, i.e. it computes
- * $\int_\Omega [u_h(x)]_c \; dx$
- * where $c$ is the vector component
- * and $u_h$ is the function
- * representation of the nodal
- * vector given as fourth
- * argument. The integral is evaluated
- * numerically using the quadrature
- * formula given as third argument.
- *
- * This function is used in the
- * "Possibilities for extensions" part of
- * the results section of @ref step_3
- * "step-3".
- *
- * @note The function is most often used
- * when solving a problem whose solution
- * is only defined up to a constant, for
- * example a pure Neumann problem or the
- * pressure in a Stokes or Navier-Stokes
- * problem. In both cases, subtracting
- * the mean value as computed by the
- * current function, from the nodal
- * vector does not generally yield the
- * desired result of a finite element
- * function with mean value zero. In
- * fact, it only works for Lagrangian
- * elements. For all other elements, you
- * will need to compute the mean value
- * and subtract it right inside the
- * evaluation routine.
- */
- template <int dim, class InVector, int spacedim>
- static double compute_mean_value (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &quadrature,
- const InVector &v,
- const unsigned int component);
-
- /**
- * Calls the other compute_mean_value()
- * function, see above, with
- * <tt>mapping=MappingQ1@<dim@>()</tt>.
- */
- template <int dim, class InVector, int spacedim>
- static double compute_mean_value (const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &quadrature,
- const InVector &v,
- const unsigned int component);
- //@}
-
- /**
- * Exception
- */
- DeclException0 (ExcInvalidBoundaryIndicator);
- /**
- * Exception
- */
- DeclException0 (ExcNonInterpolatingFE);
- /**
- * Exception
- */
- DeclException0 (ExcNoComponentSelected);
-};
+ const Mapping<dim, spacedim> &mapping = MappingQ1<dim>::mapping);
+
+
+ //@}
+ /**
+ * @name Assembling of right hand sides
+ */
+ //@{
+
+ /**
+ * Create a right hand side
+ * vector. Prior content of the
+ * given @p rhs_vector vector is
+ * deleted.
+ *
+ * See the general documentation of this
+ * class for further information.
+ */
+ template <int dim, int spacedim>
+ void create_right_hand_side (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Calls the create_right_hand_side()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, int spacedim>
+ void create_right_hand_side (const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Like the previous set of functions,
+ * but for hp objects.
+ */
+ template <int dim, int spacedim>
+ void create_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof,
+ const hp::QCollection<dim> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Like the previous set of functions,
+ * but for hp objects.
+ */
+ template <int dim, int spacedim>
+ void create_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof,
+ const hp::QCollection<dim> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Create a right hand side
+ * vector for a point source at point @p p.
+ * Prior content of the
+ * given @p rhs_vector vector is
+ * deleted.
+ *
+ * See the general documentation of this
+ * class for further information.
+ */
+ template <int dim, int spacedim>
+ void create_point_source_vector(const Mapping<dim,spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Calls the create_point_source_vector()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, int spacedim>
+ void create_point_source_vector(const DoFHandler<dim,spacedim> &dof,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Like the previous set of functions,
+ * but for hp objects.
+ */
+ template <int dim, int spacedim>
+ void create_point_source_vector(const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Like the previous set of functions,
+ * but for hp objects. The function uses
+ * the default Q1 mapping object. Note
+ * that if your hp::DoFHandler uses any
+ * active fe index other than zero, then
+ * you need to call the function above
+ * that provides a mapping object for
+ * each active fe index.
+ */
+ template <int dim, int spacedim>
+ void create_point_source_vector(const hp::DoFHandler<dim,spacedim> &dof,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector);
+
+ /**
+ * Create a right hand side
+ * vector from boundary
+ * forces. Prior content of the
+ * given @p rhs_vector vector is
+ * deleted.
+ *
+ * See the general documentation of this
+ * class for further information.
+ */
+ template <int dim, int spacedim>
+ void create_boundary_right_hand_side (const Mapping<dim,spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim-1> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
+
+ /**
+ * Calls the
+ * create_boundary_right_hand_side()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, int spacedim>
+ void create_boundary_right_hand_side (const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim-1> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
+
+ /**
+ * Same as the set of functions above,
+ * but for hp objects.
+ */
+ template <int dim, int spacedim>
+ void create_boundary_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof,
+ const hp::QCollection<dim-1> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
+
+ /**
+ * Calls the
+ * create_boundary_right_hand_side()
+ * function, see above, with a
+ * single Q1 mapping as
+ * collection. This function
+ * therefore will only work if
+ * the only active fe index in
+ * use is zero.
+ */
+ template <int dim, int spacedim>
+ void create_boundary_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof,
+ const hp::QCollection<dim-1> &q,
+ const Function<spacedim> &rhs,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators = std::set<unsigned char>());
+
+ //@}
+ /**
+ * @name Evaluation of functions
+ * and errors
+ */
+ //@{
+
+ /**
+ * Compute the error of the
+ * finite element solution.
+ * Integrate the difference
+ * between a reference function
+ * which is given as a continuous
+ * function object, and a finite
+ * element function.
+ *
+ * The value of @p exponent is
+ * used for computing $L^p$-norms
+ * and $W^{1,p}$-norms.
+ *
+ * The additional argument @p
+ * weight allows to evaluate
+ * weighted norms. The weight
+ * function may be scalar,
+ * establishing a weight in the
+ * domain for all components
+ * equally. This may be used, for
+ * instance, to only integrates
+ * over parts of the domain.
+ *
+ * The weight function may also
+ * be vector-valued, with as many
+ * components as the finite
+ * element function: Then,
+ * different components get
+ * different weights. A typical
+ * application is when the error
+ * with respect to only one or a
+ * subset of the solution
+ * variables is to be computed,
+ * in which the other components
+ * would have weight values equal
+ * to zero. The
+ * ComponentSelectFunction class
+ * is particularly useful for
+ * this purpose.
+ *
+ * The weight function is
+ * expected to be positive, but
+ * negative values are not
+ * filtered. By default, no
+ * weighting function is given,
+ * i.e. weight=1 in the whole
+ * domain for all vector
+ * components uniformly.
+ *
+ * It is assumed that the number
+ * of components of the function
+ * @p exact_solution matches that
+ * of the finite element used by
+ * @p dof.
+ *
+ * See the general documentation of this
+ * class for more information.
+ *
+ * @note Instantiations for this template
+ * are provided for some vector types
+ * (see the general documentation of the
+ * class), but only for InVectors as in
+ * the documentation of the class,
+ * OutVector only Vector<double> and
+ * Vector<float>.
+ */
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void integrate_difference (const Mapping<dim,spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const Quadrature<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight=0,
+ const double exponent = 2.);
+
+ /**
+ * Calls the integrate_difference()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void integrate_difference (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const Quadrature<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight=0,
+ const double exponent = 2.);
+
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void integrate_difference (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const hp::QCollection<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight=0,
+ const double exponent = 2.);
+
+ /**
+ * Calls the integrate_difference()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void integrate_difference (const hp::DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const hp::QCollection<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight=0,
+ const double exponent = 2.);
+
+ /**
+ * Point error evaluation. Find
+ * the first cell containing the
+ * given point and compute the
+ * difference of a (possibly
+ * vector-valued) finite element
+ * function and a continuous
+ * function (with as many vector
+ * components as the finite
+ * element) at this point.
+ *
+ * This is a wrapper function
+ * using a Q1-mapping for cell
+ * boundaries to call the other
+ * point_difference() function.
+ */
+ template <int dim, class InVector, int spacedim>
+ void point_difference (const DoFHandler<dim,spacedim>& dof,
+ const InVector& fe_function,
+ const Function<spacedim>& exact_solution,
+ Vector<double>& difference,
+ const Point<spacedim>& point);
+
+ /**
+ * Point error evaluation. Find
+ * the first cell containing the
+ * given point and compute the
+ * difference of a (possibly
+ * vector-valued) finite element
+ * function and a continuous
+ * function (with as many vector
+ * components as the finite
+ * element) at this point.
+ *
+ * Compared with the other
+ * function of the same name,
+ * this function uses an
+ * arbitrary mapping to evaluate
+ * the difference.
+ */
+ template <int dim, class InVector, int spacedim>
+ void point_difference (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim>& dof,
+ const InVector& fe_function,
+ const Function<spacedim>& exact_solution,
+ Vector<double>& difference,
+ const Point<spacedim>& point);
+
+ /**
+ * Evaluate a possibly
+ * vector-valued finite element
+ * function defined by the given
+ * DoFHandler and nodal vector at
+ * the given point, and return
+ * the (vector) value of this
+ * function through the last
+ * argument.
+ *
+ * This is a wrapper function
+ * using a Q1-mapping for cell
+ * boundaries to call the other
+ * point_difference() function.
+ */
+ template <int dim, class InVector, int spacedim>
+
+ void
+ point_value (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point,
+ Vector<double> &value);
+
+ /**
+ * Evaluate a scalar finite
+ * element function defined by
+ * the given DoFHandler and nodal
+ * vector at the given point, and
+ * return the value of this
+ * function.
+ *
+ * Compared with the other
+ * function of the same name,
+ * this is a wrapper function using
+ * a Q1-mapping for cells.
+ *
+ * This function is used in the
+ * "Possibilities for extensions" part of
+ * the results section of @ref step_3
+ * "step-3".
+ */
+ template <int dim, class InVector, int spacedim>
+
+ double
+ point_value (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point);
+
+ /**
+ * Evaluate a possibly
+ * vector-valued finite element
+ * function defined by the given
+ * DoFHandler and nodal vector at
+ * the given point, and return
+ * the (vector) value of this
+ * function through the last
+ * argument.
+ *
+ * Compared with the other
+ * function of the same name,
+ * this function uses an arbitrary
+ * mapping to evaluate the difference.
+ */
+ template <int dim, class InVector, int spacedim>
+
+ void
+ point_value (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point,
+ Vector<double> &value);
+
+ /**
+ * Evaluate a scalar finite
+ * element function defined by
+ * the given DoFHandler and nodal
+ * vector at the given point, and
+ * return the value of this
+ * function.
+ *
+ * Compared with the other
+ * function of the same name,
+ * this function uses an arbitrary
+ * mapping to evaluate the difference.
+ */
+ template <int dim, class InVector, int spacedim>
+
+ double
+ point_value (const Mapping<dim,spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point);
+
+ //@}
+ /**
+ * Mean value operations
+ */
+ //@{
+
+ /**
+ * Subtract the (algebraic) mean value
+ * from a vector. This function is most
+ * frequently used as a mean-value filter
+ * for Stokes: The pressure in Stokes'
+ * equations with only Dirichlet
+ * boundaries for the velocities is only
+ * determined up to a constant. This
+ * function allows to subtract the mean
+ * value of the pressure. It is usually
+ * called in a preconditioner and
+ * generates updates with mean value
+ * zero. The mean value is computed as
+ * the mean value of the degrees of
+ * freedom values as given by the input
+ * vector; they are not weighted by the
+ * area of cells, i.e. the mean is
+ * computed as $\sum_i v_i$, rather than
+ * as $\int_\Omega v(x) = \int_\Omega
+ * \sum_i v_i \phi_i(x)$. The latter can
+ * be obtained from the
+ * VectorTools::compute_mean_function,
+ * however.
+ *
+ * Apart from the vector @p v to operate
+ * on, this function takes a boolean mask
+ * that has a true entry for
+ * every component for which the mean
+ * value shall be computed and later
+ * subtracted. The argument is used to
+ * denote which components of the
+ * solution vector correspond to the
+ * pressure, and avoid touching all other
+ * components of the vector, such as the
+ * velocity components.
+ *
+ * @note In the context of using this
+ * function to filter out the kernel of
+ * an operator (such as the null space of
+ * the Stokes operator that consists of
+ * the constant pressures), this function
+ * only makes sense for finite elements
+ * for which the null space indeed
+ * consists of the vector
+ * $(1,1,\ldots,1)^T$. This is the case
+ * for example for the usual Lagrange
+ * elements where the sum of all shape
+ * functions equals the function that is
+ * constant one. However, it is not true
+ * for some other functions: for example,
+ * for the FE_DGP element (another valid
+ * choice for the pressure in Stokes
+ * discretizations), the first shape
+ * function on each cell is constant
+ * while further elements are $L_2$
+ * orthogonal to it (on the reference
+ * cell); consequently, the sum of all
+ * shape functions is not equal to one,
+ * and the vector that is associated with
+ * the constant mode is not equal to
+ * $(1,1,\ldots,1)^T$. For such elements,
+ * a different procedure has to be used
+ * when subtracting the mean value.
+ */
+ void subtract_mean_value(Vector<double> &v,
+ const std::vector<bool> &p_select);
+
+ /**
+ * Compute the mean value of one
+ * component of the solution.
+ *
+ * This function integrates the
+ * chosen component over the
+ * whole domain and returns the
+ * result, i.e. it computes
+ * $\int_\Omega [u_h(x)]_c \; dx$
+ * where $c$ is the vector component
+ * and $u_h$ is the function
+ * representation of the nodal
+ * vector given as fourth
+ * argument. The integral is evaluated
+ * numerically using the quadrature
+ * formula given as third argument.
+ *
+ * This function is used in the
+ * "Possibilities for extensions" part of
+ * the results section of @ref step_3
+ * "step-3".
+ *
+ * @note The function is most often used
+ * when solving a problem whose solution
+ * is only defined up to a constant, for
+ * example a pure Neumann problem or the
+ * pressure in a Stokes or Navier-Stokes
+ * problem. In both cases, subtracting
+ * the mean value as computed by the
+ * current function, from the nodal
+ * vector does not generally yield the
+ * desired result of a finite element
+ * function with mean value zero. In
+ * fact, it only works for Lagrangian
+ * elements. For all other elements, you
+ * will need to compute the mean value
+ * and subtract it right inside the
+ * evaluation routine.
+ */
+ template <int dim, class InVector, int spacedim>
+ double compute_mean_value (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &quadrature,
+ const InVector &v,
+ const unsigned int component);
+
+ /**
+ * Calls the other compute_mean_value()
+ * function, see above, with
+ * <tt>mapping=MappingQ1@<dim@>()</tt>.
+ */
+ template <int dim, class InVector, int spacedim>
+ double compute_mean_value (const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &quadrature,
+ const InVector &v,
+ const unsigned int component);
+ //@}
+
+ /**
+ * Exception
+ */
+ DeclException0 (ExcInvalidBoundaryIndicator);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNonInterpolatingFE);
+ /**
+ * Exception
+ */
+ DeclException0 (ExcNoComponentSelected);
+}
DEAL_II_NAMESPACE_CLOSE
DEAL_II_NAMESPACE_OPEN
-template <class VECTOR, class DH>
-void VectorTools::interpolate (const Mapping<DH::dimension,DH::space_dimension> &mapping,
- const DH &dof,
- const Function<DH::space_dimension> &function,
- VECTOR &vec)
+
+namespace VectorTools
{
- const unsigned int dim=DH::dimension;
-
- Assert (dof.get_fe().n_components() == function.n_components,
- ExcDimensionMismatch(dof.get_fe().n_components(),
- function.n_components));
-
- const hp::FECollection<DH::dimension,DH::space_dimension> fe (dof.get_fe());
- const unsigned int n_components = fe.n_components();
- const bool fe_is_system = (n_components != 1);
-
- typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
-
- // For FESystems many of the
- // unit_support_points will appear
- // multiple times, as a point may be
- // unit_support_point for several of the
- // components of the system. The following
- // is rather complicated, but at least
- // attempts to avoid evaluating the
- // vectorfunction multiple times at the
- // same point on a cell.
- //
- // note that we have to set up all of the
- // following arrays for each of the
- // elements in the FECollection (which
- // means only once if this is for a regular
- // DoFHandler)
- std::vector<std::vector<Point<dim> > > unit_support_points (fe.size());
- for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
- {
- unit_support_points[fe_index] = fe[fe_index].get_unit_support_points();
- Assert (unit_support_points[fe_index].size() != 0,
- ExcNonInterpolatingFE());
- }
+
+ template <class VECTOR, class DH>
+ void interpolate (const Mapping<DH::dimension,DH::space_dimension> &mapping,
+ const DH &dof,
+ const Function<DH::space_dimension> &function,
+ VECTOR &vec)
+ {
+ const unsigned int dim=DH::dimension;
+
+ Assert (dof.get_fe().n_components() == function.n_components,
+ ExcDimensionMismatch(dof.get_fe().n_components(),
+ function.n_components));
+
+ const hp::FECollection<DH::dimension,DH::space_dimension> fe (dof.get_fe());
+ const unsigned int n_components = fe.n_components();
+ const bool fe_is_system = (n_components != 1);
+
+ typename DH::active_cell_iterator cell = dof.begin_active(),
+ endc = dof.end();
+
+ // For FESystems many of the
+ // unit_support_points will appear
+ // multiple times, as a point may be
+ // unit_support_point for several of the
+ // components of the system. The following
+ // is rather complicated, but at least
+ // attempts to avoid evaluating the
+ // vectorfunction multiple times at the
+ // same point on a cell.
+ //
+ // note that we have to set up all of the
+ // following arrays for each of the
+ // elements in the FECollection (which
+ // means only once if this is for a regular
+ // DoFHandler)
+ std::vector<std::vector<Point<dim> > > unit_support_points (fe.size());
+ for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
+ {
+ unit_support_points[fe_index] = fe[fe_index].get_unit_support_points();
+ Assert (unit_support_points[fe_index].size() != 0,
+ ExcNonInterpolatingFE());
+ }
- // Find the support points on a cell that
- // are mentioned multiple times in
- // unit_support_points. Mark the first
- // representative of each support point
- // mentioned multiple times by appending
- // its dof index to dofs_of_rep_points.
- // Each multiple point gets to know the dof
- // index of its representative point by the
- // dof_to_rep_dof_table.
-
- // the following vector collects all dofs i,
- // 0<=i<fe.dofs_per_cell, for that
- // unit_support_points[i]
- // is a representative one. i.e.
- // the following vector collects all rep dofs.
- // the position of a rep dof within this vector
- // is called rep index.
- std::vector<std::vector<unsigned int> > dofs_of_rep_points(fe.size());
- // the following table converts a dof i
- // to the rep index.
- std::vector<std::vector<unsigned int> > dof_to_rep_index_table(fe.size());
-
- std::vector<unsigned int> n_rep_points (fe.size(), 0);
-
- for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
- {
- for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
- {
- bool representative=true;
- // the following loop is looped
- // the other way round to get
- // the minimal effort of
- // O(fe.dofs_per_cell) for multiple
- // support points that are placed
- // one after the other.
- for (unsigned int j=dofs_of_rep_points[fe_index].size(); j>0; --j)
- if (unit_support_points[fe_index][i]
- == unit_support_points[fe_index][dofs_of_rep_points[fe_index][j-1]])
+ // Find the support points on a cell that
+ // are mentioned multiple times in
+ // unit_support_points. Mark the first
+ // representative of each support point
+ // mentioned multiple times by appending
+ // its dof index to dofs_of_rep_points.
+ // Each multiple point gets to know the dof
+ // index of its representative point by the
+ // dof_to_rep_dof_table.
+
+ // the following vector collects all dofs i,
+ // 0<=i<fe.dofs_per_cell, for that
+ // unit_support_points[i]
+ // is a representative one. i.e.
+ // the following vector collects all rep dofs.
+ // the position of a rep dof within this vector
+ // is called rep index.
+ std::vector<std::vector<unsigned int> > dofs_of_rep_points(fe.size());
+ // the following table converts a dof i
+ // to the rep index.
+ std::vector<std::vector<unsigned int> > dof_to_rep_index_table(fe.size());
+
+ std::vector<unsigned int> n_rep_points (fe.size(), 0);
+
+ for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
+ {
+ for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
+ {
+ bool representative=true;
+ // the following loop is looped
+ // the other way round to get
+ // the minimal effort of
+ // O(fe.dofs_per_cell) for multiple
+ // support points that are placed
+ // one after the other.
+ for (unsigned int j=dofs_of_rep_points[fe_index].size(); j>0; --j)
+ if (unit_support_points[fe_index][i]
+ == unit_support_points[fe_index][dofs_of_rep_points[fe_index][j-1]])
+ {
+ dof_to_rep_index_table[fe_index].push_back(j-1);
+ representative=false;
+ break;
+ }
+
+ if (representative)
{
- dof_to_rep_index_table[fe_index].push_back(j-1);
- representative=false;
- break;
+ // rep_index=dofs_of_rep_points.size()
+ dof_to_rep_index_table[fe_index].push_back(dofs_of_rep_points[fe_index].size());
+ // dofs_of_rep_points[rep_index]=i
+ dofs_of_rep_points[fe_index].push_back(i);
+ ++n_rep_points[fe_index];
}
+ }
- if (representative)
- {
- // rep_index=dofs_of_rep_points.size()
- dof_to_rep_index_table[fe_index].push_back(dofs_of_rep_points[fe_index].size());
- // dofs_of_rep_points[rep_index]=i
- dofs_of_rep_points[fe_index].push_back(i);
- ++n_rep_points[fe_index];
- }
- }
-
- Assert(dofs_of_rep_points[fe_index].size()==n_rep_points[fe_index],
- ExcInternalError());
- Assert(dof_to_rep_index_table[fe_index].size()==fe[fe_index].dofs_per_cell,
- ExcInternalError());
- }
+ Assert(dofs_of_rep_points[fe_index].size()==n_rep_points[fe_index],
+ ExcInternalError());
+ Assert(dof_to_rep_index_table[fe_index].size()==fe[fe_index].dofs_per_cell,
+ ExcInternalError());
+ }
- const unsigned int max_rep_points = *std::max_element (n_rep_points.begin(),
- n_rep_points.end());
- std::vector<unsigned int> dofs_on_cell (fe.max_dofs_per_cell());
- std::vector<Point<DH::space_dimension> > rep_points (max_rep_points);
-
- // get space for the values of the
- // function at the rep support points.
- //
- // have two versions, one for system fe
- // and one for scalar ones, to take the
- // more efficient one respectively
- std::vector<std::vector<double> > function_values_scalar(fe.size());
- std::vector<std::vector<Vector<double> > > function_values_system(fe.size());
-
- // Make a quadrature rule from support points
- // to feed it into FEValues
- hp::QCollection<dim> support_quadrature;
- for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
- support_quadrature.push_back (Quadrature<dim>(unit_support_points[fe_index]));
-
- // Transformed support points are computed by
- // FEValues
- hp::MappingCollection<dim,DH::space_dimension> mapping_collection (mapping);
-
- hp::FEValues<dim, DH::space_dimension> fe_values (mapping_collection,
- fe, support_quadrature, update_quadrature_points);
-
- for (; cell!=endc; ++cell)
- if (cell->is_locally_owned())
- {
- const unsigned int fe_index = cell->active_fe_index();
+ const unsigned int max_rep_points = *std::max_element (n_rep_points.begin(),
+ n_rep_points.end());
+ std::vector<unsigned int> dofs_on_cell (fe.max_dofs_per_cell());
+ std::vector<Point<DH::space_dimension> > rep_points (max_rep_points);
+
+ // get space for the values of the
+ // function at the rep support points.
+ //
+ // have two versions, one for system fe
+ // and one for scalar ones, to take the
+ // more efficient one respectively
+ std::vector<std::vector<double> > function_values_scalar(fe.size());
+ std::vector<std::vector<Vector<double> > > function_values_system(fe.size());
+
+ // Make a quadrature rule from support points
+ // to feed it into FEValues
+ hp::QCollection<dim> support_quadrature;
+ for (unsigned int fe_index=0; fe_index<fe.size(); ++fe_index)
+ support_quadrature.push_back (Quadrature<dim>(unit_support_points[fe_index]));
+
+ // Transformed support points are computed by
+ // FEValues
+ hp::MappingCollection<dim,DH::space_dimension> mapping_collection (mapping);
+
+ hp::FEValues<dim, DH::space_dimension> fe_values (mapping_collection,
+ fe, support_quadrature, update_quadrature_points);
+
+ for (; cell!=endc; ++cell)
+ if (cell->is_locally_owned())
+ {
+ const unsigned int fe_index = cell->active_fe_index();
- // for each cell:
- // get location of finite element
- // support_points
- fe_values.reinit(cell);
- const std::vector<Point<DH::space_dimension> >& support_points =
- fe_values.get_present_fe_values().get_quadrature_points();
+ // for each cell:
+ // get location of finite element
+ // support_points
+ fe_values.reinit(cell);
+ const std::vector<Point<DH::space_dimension> >& support_points =
+ fe_values.get_present_fe_values().get_quadrature_points();
- // pick out the representative
- // support points
- rep_points.resize (dofs_of_rep_points[fe_index].size());
- for (unsigned int j=0; j<dofs_of_rep_points[fe_index].size(); ++j)
- rep_points[j] = support_points[dofs_of_rep_points[fe_index][j]];
+ // pick out the representative
+ // support points
+ rep_points.resize (dofs_of_rep_points[fe_index].size());
+ for (unsigned int j=0; j<dofs_of_rep_points[fe_index].size(); ++j)
+ rep_points[j] = support_points[dofs_of_rep_points[fe_index][j]];
- // get indices of the dofs on this cell
- dofs_on_cell.resize (fe[fe_index].dofs_per_cell);
- cell->get_dof_indices (dofs_on_cell);
+ // get indices of the dofs on this cell
+ dofs_on_cell.resize (fe[fe_index].dofs_per_cell);
+ cell->get_dof_indices (dofs_on_cell);
- if (fe_is_system)
- {
- // get function values at
- // these points. Here: get
- // all components
- function_values_system[fe_index]
- .resize (n_rep_points[fe_index],
- Vector<double> (fe[fe_index].n_components()));
- function.vector_value_list (rep_points,
- function_values_system[fe_index]);
- // distribute the function
- // values to the global
- // vector
- for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
+ if (fe_is_system)
{
- const unsigned int component
- = fe[fe_index].system_to_component_index(i).first;
- const unsigned int rep_dof=dof_to_rep_index_table[fe_index][i];
- vec(dofs_on_cell[i])
- = function_values_system[fe_index][rep_dof](component);
+ // get function values at
+ // these points. Here: get
+ // all components
+ function_values_system[fe_index]
+ .resize (n_rep_points[fe_index],
+ Vector<double> (fe[fe_index].n_components()));
+ function.vector_value_list (rep_points,
+ function_values_system[fe_index]);
+ // distribute the function
+ // values to the global
+ // vector
+ for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
+ {
+ const unsigned int component
+ = fe[fe_index].system_to_component_index(i).first;
+ const unsigned int rep_dof=dof_to_rep_index_table[fe_index][i];
+ vec(dofs_on_cell[i])
+ = function_values_system[fe_index][rep_dof](component);
+ }
+ }
+ else
+ {
+ // get first component only,
+ // which is the only component
+ // in the function anyway
+ function_values_scalar[fe_index].resize (n_rep_points[fe_index]);
+ function.value_list (rep_points,
+ function_values_scalar[fe_index],
+ 0);
+ // distribute the function
+ // values to the global
+ // vector
+ for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
+ vec(dofs_on_cell[i])
+ = function_values_scalar[fe_index][dof_to_rep_index_table[fe_index][i]];
}
}
- else
- {
- // get first component only,
- // which is the only component
- // in the function anyway
- function_values_scalar[fe_index].resize (n_rep_points[fe_index]);
- function.value_list (rep_points,
- function_values_scalar[fe_index],
- 0);
- // distribute the function
- // values to the global
- // vector
- for (unsigned int i=0; i<fe[fe_index].dofs_per_cell; ++i)
- vec(dofs_on_cell[i])
- = function_values_scalar[fe_index][dof_to_rep_index_table[fe_index][i]];
- }
- }
-}
+ }
-template <class VECTOR, class DH>
-void VectorTools::interpolate (const DH &dof,
- const Function<DH::space_dimension> &function,
- VECTOR &vec)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- interpolate(StaticMappingQ1<DH::dimension, DH::space_dimension>::mapping,
- dof, function, vec);
-}
+ template <class VECTOR, class DH>
+ void interpolate (const DH &dof,
+ const Function<DH::space_dimension> &function,
+ VECTOR &vec)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ interpolate(StaticMappingQ1<DH::dimension, DH::space_dimension>::mapping,
+ dof, function, vec);
+ }
-template <int dim, class InVector, class OutVector, int spacedim>
-void
-VectorTools::interpolate (const DoFHandler<dim,spacedim> &dof_1,
- const DoFHandler<dim,spacedim> &dof_2,
- const FullMatrix<double> &transfer,
- const InVector &data_1,
- OutVector &data_2)
-{
- Vector<double> cell_data_1(dof_1.get_fe().dofs_per_cell);
- Vector<double> cell_data_2(dof_2.get_fe().dofs_per_cell);
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ interpolate (const DoFHandler<dim,spacedim> &dof_1,
+ const DoFHandler<dim,spacedim> &dof_2,
+ const FullMatrix<double> &transfer,
+ const InVector &data_1,
+ OutVector &data_2)
+ {
+ Vector<double> cell_data_1(dof_1.get_fe().dofs_per_cell);
+ Vector<double> cell_data_2(dof_2.get_fe().dofs_per_cell);
- std::vector<short unsigned int> touch_count (dof_2.n_dofs(), 0);
- std::vector<unsigned int> local_dof_indices (dof_2.get_fe().dofs_per_cell);
+ std::vector<short unsigned int> touch_count (dof_2.n_dofs(), 0);
+ std::vector<unsigned int> local_dof_indices (dof_2.get_fe().dofs_per_cell);
- typename DoFHandler<dim,spacedim>::active_cell_iterator h = dof_1.begin_active();
- typename DoFHandler<dim,spacedim>::active_cell_iterator l = dof_2.begin_active();
- const typename DoFHandler<dim,spacedim>::cell_iterator endh = dof_1.end();
+ typename DoFHandler<dim,spacedim>::active_cell_iterator h = dof_1.begin_active();
+ typename DoFHandler<dim,spacedim>::active_cell_iterator l = dof_2.begin_active();
+ const typename DoFHandler<dim,spacedim>::cell_iterator endh = dof_1.end();
- for(; h != endh; ++h, ++l)
- {
- h->get_dof_values(data_1, cell_data_1);
- transfer.vmult(cell_data_2, cell_data_1);
+ for(; h != endh; ++h, ++l)
+ {
+ h->get_dof_values(data_1, cell_data_1);
+ transfer.vmult(cell_data_2, cell_data_1);
- l->get_dof_indices (local_dof_indices);
+ l->get_dof_indices (local_dof_indices);
- // distribute cell vector
- for (unsigned int j=0; j<dof_2.get_fe().dofs_per_cell; ++j)
- {
- data_2(local_dof_indices[j]) += cell_data_2(j);
+ // distribute cell vector
+ for (unsigned int j=0; j<dof_2.get_fe().dofs_per_cell; ++j)
+ {
+ data_2(local_dof_indices[j]) += cell_data_2(j);
- // count, how often we have
- // added to this dof
- Assert (touch_count[local_dof_indices[j]] < 255,
- ExcInternalError());
- ++touch_count[local_dof_indices[j]];
+ // count, how often we have
+ // added to this dof
+ Assert (touch_count[local_dof_indices[j]] < 255,
+ ExcInternalError());
+ ++touch_count[local_dof_indices[j]];
+ };
};
- };
- // compute the mean value of the
- // sum which we have placed in each
- // entry of the output vector
- for (unsigned int i=0; i<dof_2.n_dofs(); ++i)
- {
- Assert (touch_count[i] != 0,
- ExcInternalError());
+ // compute the mean value of the
+ // sum which we have placed in each
+ // entry of the output vector
+ for (unsigned int i=0; i<dof_2.n_dofs(); ++i)
+ {
+ Assert (touch_count[i] != 0,
+ ExcInternalError());
- data_2(i) /= touch_count[i];
- };
-}
+ data_2(i) /= touch_count[i];
+ };
+ }
-namespace internal
-{
- namespace VectorTools
+ namespace internal
{
void
interpolate_zero_boundary_values (const dealii::DoFHandler<1> &dof_handler,
std::map<unsigned int,double> &boundary_values)
{
- // we only need to find the
- // left-most and right-most
- // vertex and query its vertex
- // dof indices. that's easy :-)
+ // we only need to find the
+ // left-most and right-most
+ // vertex and query its vertex
+ // dof indices. that's easy :-)
for (unsigned direction=0; direction<2; ++direction)
- {
- dealii::DoFHandler<1>::cell_iterator
- cell = dof_handler.begin(0);
- while (!cell->at_boundary(direction))
- cell = cell->neighbor(direction);
-
- for (unsigned int i=0; i<dof_handler.get_fe().dofs_per_vertex; ++i)
- boundary_values[cell->vertex_dof_index (direction, i)] = 0.;
- }
+ {
+ dealii::DoFHandler<1>::cell_iterator
+ cell = dof_handler.begin(0);
+ while (!cell->at_boundary(direction))
+ cell = cell->neighbor(direction);
+
+ for (unsigned int i=0; i<dof_handler.get_fe().dofs_per_vertex; ++i)
+ boundary_values[cell->vertex_dof_index (direction, i)] = 0.;
+ }
}
- // codimension 1
+ // codimension 1
void
interpolate_zero_boundary_values (const dealii::DoFHandler<1,2> &dof_handler,
std::map<unsigned int,double> &boundary_values)
{
- // we only need to find the
- // left-most and right-most
- // vertex and query its vertex
- // dof indices. that's easy :-)
+ // we only need to find the
+ // left-most and right-most
+ // vertex and query its vertex
+ // dof indices. that's easy :-)
for (unsigned direction=0; direction<2; ++direction)
- {
- dealii::DoFHandler<1,2>::cell_iterator
- cell = dof_handler.begin(0);
- while (!cell->at_boundary(direction))
- cell = cell->neighbor(direction);
-
- for (unsigned int i=0; i<dof_handler.get_fe().dofs_per_vertex; ++i)
- boundary_values[cell->vertex_dof_index (direction, i)] = 0.;
- }
+ {
+ dealii::DoFHandler<1,2>::cell_iterator
+ cell = dof_handler.begin(0);
+ while (!cell->at_boundary(direction))
+ cell = cell->neighbor(direction);
+
+ for (unsigned int i=0; i<dof_handler.get_fe().dofs_per_vertex; ++i)
+ boundary_values[cell->vertex_dof_index (direction, i)] = 0.;
+ }
}
template <int dim, int spacedim>
void
interpolate_zero_boundary_values (const dealii::DoFHandler<dim,spacedim> &dof_handler,
- std::map<unsigned int,double> &boundary_values)
+ std::map<unsigned int,double> &boundary_values)
{
const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
// the boundary, not only by
// one line or one vertex
typename dealii::DoFHandler<dim,spacedim>::active_face_iterator
- face = dof_handler.begin_active_face(),
- endf = dof_handler.end_face();
+ face = dof_handler.begin_active_face(),
+ endf = dof_handler.end_face();
std::vector<unsigned int> face_dof_indices (fe.dofs_per_face);
for (; face!=endf; ++face)
if (face->at_boundary())
}
}
}
-}
-template <int dim, class VECTOR, int spacedim>
-void VectorTools::project (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const ConstraintMatrix &constraints,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &function,
- VECTOR &vec_result,
- const bool enforce_zero_boundary,
- const Quadrature<dim-1> &q_boundary,
- const bool project_to_boundary_first)
-{
- Assert (dof.get_fe().n_components() == function.n_components,
- ExcDimensionMismatch(dof.get_fe().n_components(),
- function.n_components));
-
- Assert (vec_result.size() == dof.n_dofs(),
- ExcDimensionMismatch (vec_result.size(), dof.n_dofs()));
-
- // make up boundary values
- std::map<unsigned int,double> boundary_values;
-
- if (enforce_zero_boundary == true)
- // no need to project boundary
- // values, but enforce
- // homogeneous boundary values
- // anyway
- internal::VectorTools::
- interpolate_zero_boundary_values (dof, boundary_values);
-
- else
- // no homogeneous boundary values
- if (project_to_boundary_first == true)
- // boundary projection required
- {
- // set up a list of boundary
- // functions for the
- // different boundary
- // parts. We want the
- // function to hold on
- // all parts of the boundary
- typename FunctionMap<spacedim>::type boundary_functions;
- for (unsigned char c=0; c<255; ++c)
- boundary_functions[c] = &function;
- project_boundary_values (dof, boundary_functions, q_boundary,
- boundary_values);
- }
+ template <int dim, class VECTOR, int spacedim>
+ void project (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const ConstraintMatrix &constraints,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &function,
+ VECTOR &vec_result,
+ const bool enforce_zero_boundary,
+ const Quadrature<dim-1> &q_boundary,
+ const bool project_to_boundary_first)
+ {
+ Assert (dof.get_fe().n_components() == function.n_components,
+ ExcDimensionMismatch(dof.get_fe().n_components(),
+ function.n_components));
+
+ Assert (vec_result.size() == dof.n_dofs(),
+ ExcDimensionMismatch (vec_result.size(), dof.n_dofs()));
+
+ // make up boundary values
+ std::map<unsigned int,double> boundary_values;
+
+ if (enforce_zero_boundary == true)
+ // no need to project boundary
+ // values, but enforce
+ // homogeneous boundary values
+ // anyway
+ internal::
+ interpolate_zero_boundary_values (dof, boundary_values);
+
+ else
+ // no homogeneous boundary values
+ if (project_to_boundary_first == true)
+ // boundary projection required
+ {
+ // set up a list of boundary
+ // functions for the
+ // different boundary
+ // parts. We want the
+ // function to hold on
+ // all parts of the boundary
+ typename FunctionMap<spacedim>::type boundary_functions;
+ for (unsigned char c=0; c<255; ++c)
+ boundary_functions[c] = &function;
+ project_boundary_values (dof, boundary_functions, q_boundary,
+ boundary_values);
+ }
- // set up mass matrix and right hand side
- Vector<double> vec (dof.n_dofs());
- SparsityPattern sparsity;
+ // set up mass matrix and right hand side
+ Vector<double> vec (dof.n_dofs());
+ SparsityPattern sparsity;
- // use csp to consume less memory and to
- // still be fast
- {
- CompressedSimpleSparsityPattern csp (dof.n_dofs(), dof.n_dofs());
- DoFTools::make_sparsity_pattern (dof, csp, constraints);
+ // use csp to consume less memory and to
+ // still be fast
+ {
+ CompressedSimpleSparsityPattern csp (dof.n_dofs(), dof.n_dofs());
+ DoFTools::make_sparsity_pattern (dof, csp, constraints);
+
+ sparsity.copy_from (csp);
+ }
- sparsity.copy_from (csp);
+ SparseMatrix<double> mass_matrix (sparsity);
+ Vector<double> tmp (mass_matrix.n());
+
+ // create mass matrix and rhs at once,
+ // which is faster.
+ MatrixCreator::create_mass_matrix (mapping, dof, quadrature, mass_matrix,
+ function, tmp);
+
+ constraints.condense (mass_matrix);
+ constraints.condense (tmp);
+ if (boundary_values.size() != 0)
+ MatrixTools::apply_boundary_values (boundary_values,
+ mass_matrix, vec, tmp,
+ true);
+ // Allow for a maximum of 5*n
+ // steps to reduce the residual by
+ // 10^-12. n steps may not be
+ // sufficient, since roundoff
+ // errors may accumulate for badly
+ // conditioned matrices
+ ReductionControl control(5*tmp.size(), 0., 1e-12, false, false);
+ GrowingVectorMemory<> memory;
+ SolverCG<> cg(control,memory);
+
+ PreconditionSSOR<> prec;
+ prec.initialize(mass_matrix, 1.2);
+ // solve
+ cg.solve (mass_matrix, vec, tmp, prec);
+
+ // distribute solution
+ constraints.distribute (vec);
+
+ // copy vec into vec_result. we
+ // can't use ve_result itself
+ // above, since it may be of
+ // another type than Vector<double>
+ // and that wouldn't necessarily go
+ // together with the matrix and
+ // other functions
+ for (unsigned int i=0; i<vec.size(); ++i)
+ vec_result(i) = vec(i);
}
- SparseMatrix<double> mass_matrix (sparsity);
- Vector<double> tmp (mass_matrix.n());
-
- // create mass matrix and rhs at once,
- // which is faster.
- MatrixCreator::create_mass_matrix (mapping, dof, quadrature, mass_matrix,
- function, tmp);
-
- constraints.condense (mass_matrix);
- constraints.condense (tmp);
- if (boundary_values.size() != 0)
- MatrixTools::apply_boundary_values (boundary_values,
- mass_matrix, vec, tmp,
- true);
- // Allow for a maximum of 5*n
- // steps to reduce the residual by
- // 10^-12. n steps may not be
- // sufficient, since roundoff
- // errors may accumulate for badly
- // conditioned matrices
- ReductionControl control(5*tmp.size(), 0., 1e-12, false, false);
- GrowingVectorMemory<> memory;
- SolverCG<> cg(control,memory);
-
- PreconditionSSOR<> prec;
- prec.initialize(mass_matrix, 1.2);
- // solve
- cg.solve (mass_matrix, vec, tmp, prec);
-
- // distribute solution
- constraints.distribute (vec);
-
- // copy vec into vec_result. we
- // can't use ve_result itself
- // above, since it may be of
- // another type than Vector<double>
- // and that wouldn't necessarily go
- // together with the matrix and
- // other functions
- for (unsigned int i=0; i<vec.size(); ++i)
- vec_result(i) = vec(i);
-}
+ template <int dim, class VECTOR, int spacedim>
+ void project (const DoFHandler<dim,spacedim> &dof,
+ const ConstraintMatrix &constraints,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &function,
+ VECTOR &vec,
+ const bool enforce_zero_boundary,
+ const Quadrature<dim-1> &q_boundary,
+ const bool project_to_boundary_first)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ project(StaticMappingQ1<dim,spacedim>::mapping, dof, constraints, quadrature, function, vec,
+ enforce_zero_boundary, q_boundary, project_to_boundary_first);
+ }
-template <int dim, class VECTOR, int spacedim>
-void VectorTools::project (const DoFHandler<dim,spacedim> &dof,
- const ConstraintMatrix &constraints,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &function,
- VECTOR &vec,
- const bool enforce_zero_boundary,
- const Quadrature<dim-1> &q_boundary,
- const bool project_to_boundary_first)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- project(StaticMappingQ1<dim,spacedim>::mapping, dof, constraints, quadrature, function, vec,
- enforce_zero_boundary, q_boundary, project_to_boundary_first);
-}
+ template <int dim, int spacedim>
+ void create_right_hand_side (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof_handler,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector)
+ {
+ const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
+ Assert (fe.n_components() == rhs_function.n_components,
+ ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
+ rhs_vector = 0;
+
+ UpdateFlags update_flags = UpdateFlags(update_values |
+ update_quadrature_points |
+ update_JxW_values);
+ FEValues<dim,spacedim> fe_values (mapping, fe, quadrature, update_flags);
+
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points,
+ n_components = fe.n_components();
+
+ std::vector<unsigned int> dofs (dofs_per_cell);
+ Vector<double> cell_vector (dofs_per_cell);
+
+ typename DoFHandler<dim,spacedim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+
+ if (n_components==1)
+ {
+ std::vector<double> rhs_values(n_q_points);
-template <int dim, int spacedim>
-void VectorTools::create_right_hand_side (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof_handler,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector)
-{
- const FiniteElement<dim,spacedim> &fe = dof_handler.get_fe();
- Assert (fe.n_components() == rhs_function.n_components,
- ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- rhs_vector = 0;
-
- UpdateFlags update_flags = UpdateFlags(update_values |
- update_quadrature_points |
- update_JxW_values);
- FEValues<dim,spacedim> fe_values (mapping, fe, quadrature, update_flags);
-
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points,
- n_components = fe.n_components();
-
- std::vector<unsigned int> dofs (dofs_per_cell);
- Vector<double> cell_vector (dofs_per_cell);
-
- typename DoFHandler<dim,spacedim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
-
- if (n_components==1)
- {
- std::vector<double> rhs_values(n_q_points);
+ for (; cell!=endc; ++cell)
+ {
+ fe_values.reinit(cell);
- for (; cell!=endc; ++cell)
- {
- fe_values.reinit(cell);
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.value_list (fe_values.get_quadrature_points(),
+ rhs_values);
+
+ cell_vector = 0;
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_vector(i) += rhs_values[point] *
+ fe_values.shape_value(i,point) *
+ weights[point];
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.value_list (fe_values.get_quadrature_points(),
- rhs_values);
+ cell->get_dof_indices (dofs);
- cell_vector = 0;
- for (unsigned int point=0; point<n_q_points; ++point)
for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_vector(i) += rhs_values[point] *
- fe_values.shape_value(i,point) *
- weights[point];
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
- cell->get_dof_indices (dofs);
+ }
+ else
+ {
+ std::vector<Vector<double> > rhs_values(n_q_points,
+ Vector<double>(n_components));
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
+ for (; cell!=endc; ++cell)
+ {
+ fe_values.reinit(cell);
- }
- else
- {
- std::vector<Vector<double> > rhs_values(n_q_points,
- Vector<double>(n_components));
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.vector_value_list (fe_values.get_quadrature_points(),
+ rhs_values);
- for (; cell!=endc; ++cell)
- {
- fe_values.reinit(cell);
+ cell_vector = 0;
+ // Use the faster code if the
+ // FiniteElement is primitive
+ if (fe.is_primitive ())
+ {
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ const unsigned int component
+ = fe.system_to_component_index(i).first;
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.vector_value_list (fe_values.get_quadrature_points(),
- rhs_values);
+ cell_vector(i) += rhs_values[point](component) *
+ fe_values.shape_value(i,point) *
+ weights[point];
+ }
+ }
+ else
+ {
+ // Otherwise do it the way
+ // proposed for vector valued
+ // elements
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
+ if (fe.get_nonzero_components(i)[comp_i])
+ {
+ cell_vector(i) += rhs_values[point](comp_i) *
+ fe_values.shape_value_component(i,point,comp_i) *
+ weights[point];
+ }
+ }
- cell_vector = 0;
- // Use the faster code if the
- // FiniteElement is primitive
- if (fe.is_primitive ())
- {
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- const unsigned int component
- = fe.system_to_component_index(i).first;
+ cell->get_dof_indices (dofs);
- cell_vector(i) += rhs_values[point](component) *
- fe_values.shape_value(i,point) *
- weights[point];
- }
- }
- else
- {
- // Otherwise do it the way
- // proposed for vector valued
- // elements
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
- if (fe.get_nonzero_components(i)[comp_i])
- {
- cell_vector(i) += rhs_values[point](comp_i) *
- fe_values.shape_value_component(i,point,comp_i) *
- weights[point];
- }
- }
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ }
- cell->get_dof_indices (dofs);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
-}
+ template <int dim, int spacedim>
+ void create_right_hand_side (const DoFHandler<dim,spacedim> &dof_handler,
+ const Quadrature<dim> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ create_right_hand_side(StaticMappingQ1<dim,spacedim>::mapping, dof_handler, quadrature,
+ rhs_function, rhs_vector);
+ }
-template <int dim, int spacedim>
-void VectorTools::create_right_hand_side (const DoFHandler<dim,spacedim> &dof_handler,
- const Quadrature<dim> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_right_hand_side(StaticMappingQ1<dim,spacedim>::mapping, dof_handler, quadrature,
- rhs_function, rhs_vector);
-}
+ template <int dim, int spacedim>
+ void create_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const hp::QCollection<dim> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector)
+ {
+ const hp::FECollection<dim,spacedim> &fe = dof_handler.get_fe();
+ Assert (fe.n_components() == rhs_function.n_components,
+ ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
+ rhs_vector = 0;
+ UpdateFlags update_flags = UpdateFlags(update_values |
+ update_quadrature_points |
+ update_JxW_values);
+ hp::FEValues<dim,spacedim> x_fe_values (mapping, fe, quadrature, update_flags);
-template <int dim, int spacedim>
-void VectorTools::create_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof_handler,
- const hp::QCollection<dim> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector)
-{
- const hp::FECollection<dim,spacedim> &fe = dof_handler.get_fe();
- Assert (fe.n_components() == rhs_function.n_components,
- ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- rhs_vector = 0;
+ const unsigned int n_components = fe.n_components();
- UpdateFlags update_flags = UpdateFlags(update_values |
- update_quadrature_points |
- update_JxW_values);
- hp::FEValues<dim,spacedim> x_fe_values (mapping, fe, quadrature, update_flags);
+ std::vector<unsigned int> dofs (fe.max_dofs_per_cell());
+ Vector<double> cell_vector (fe.max_dofs_per_cell());
- const unsigned int n_components = fe.n_components();
+ typename hp::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
- std::vector<unsigned int> dofs (fe.max_dofs_per_cell());
- Vector<double> cell_vector (fe.max_dofs_per_cell());
+ if (n_components==1)
+ {
+ std::vector<double> rhs_values;
- typename hp::DoFHandler<dim,spacedim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ {
+ x_fe_values.reinit(cell);
- if (n_components==1)
- {
- std::vector<double> rhs_values;
+ const FEValues<dim,spacedim> &fe_values = x_fe_values.get_present_fe_values();
- for (; cell!=endc; ++cell)
- {
- x_fe_values.reinit(cell);
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points;
+ rhs_values.resize (n_q_points);
+ dofs.resize (dofs_per_cell);
+ cell_vector.reinit (dofs_per_cell);
- const FEValues<dim,spacedim> &fe_values = x_fe_values.get_present_fe_values();
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.value_list (fe_values.get_quadrature_points(),
+ rhs_values);
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points;
- rhs_values.resize (n_q_points);
- dofs.resize (dofs_per_cell);
- cell_vector.reinit (dofs_per_cell);
+ cell_vector = 0;
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_vector(i) += rhs_values[point] *
+ fe_values.shape_value(i,point) *
+ weights[point];
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.value_list (fe_values.get_quadrature_points(),
- rhs_values);
+ cell->get_dof_indices (dofs);
- cell_vector = 0;
- for (unsigned int point=0; point<n_q_points; ++point)
for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_vector(i) += rhs_values[point] *
- fe_values.shape_value(i,point) *
- weights[point];
-
- cell->get_dof_indices (dofs);
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
- }
- else
- {
- std::vector<Vector<double> > rhs_values;
+ }
+ else
+ {
+ std::vector<Vector<double> > rhs_values;
- for (; cell!=endc; ++cell)
- {
- x_fe_values.reinit(cell);
+ for (; cell!=endc; ++cell)
+ {
+ x_fe_values.reinit(cell);
- const FEValues<dim,spacedim> &fe_values = x_fe_values.get_present_fe_values();
+ const FEValues<dim,spacedim> &fe_values = x_fe_values.get_present_fe_values();
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points;
- rhs_values.resize (n_q_points,
- Vector<double>(n_components));
- dofs.resize (dofs_per_cell);
- cell_vector.reinit (dofs_per_cell);
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points;
+ rhs_values.resize (n_q_points,
+ Vector<double>(n_components));
+ dofs.resize (dofs_per_cell);
+ cell_vector.reinit (dofs_per_cell);
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.vector_value_list (fe_values.get_quadrature_points(),
- rhs_values);
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.vector_value_list (fe_values.get_quadrature_points(),
+ rhs_values);
- cell_vector = 0;
+ cell_vector = 0;
- // Use the faster code if the
- // FiniteElement is primitive
- if (cell->get_fe().is_primitive ())
- {
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- const unsigned int component
- = cell->get_fe().system_to_component_index(i).first;
+ // Use the faster code if the
+ // FiniteElement is primitive
+ if (cell->get_fe().is_primitive ())
+ {
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ const unsigned int component
+ = cell->get_fe().system_to_component_index(i).first;
- cell_vector(i) += rhs_values[point](component) *
- fe_values.shape_value(i,point) *
- weights[point];
- }
- }
- else
- {
- // Otherwise do it the way proposed
- // for vector valued elements
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
- if (cell->get_fe().get_nonzero_components(i)[comp_i])
- {
- cell_vector(i) += rhs_values[point](comp_i) *
- fe_values.shape_value_component(i,point,comp_i) *
- weights[point];
- }
- }
+ cell_vector(i) += rhs_values[point](component) *
+ fe_values.shape_value(i,point) *
+ weights[point];
+ }
+ }
+ else
+ {
+ // Otherwise do it the way proposed
+ // for vector valued elements
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
+ if (cell->get_fe().get_nonzero_components(i)[comp_i])
+ {
+ cell_vector(i) += rhs_values[point](comp_i) *
+ fe_values.shape_value_component(i,point,comp_i) *
+ weights[point];
+ }
+ }
- cell->get_dof_indices (dofs);
+ cell->get_dof_indices (dofs);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
-}
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ }
-template <int dim, int spacedim>
-void VectorTools::create_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof_handler,
- const hp::QCollection<dim> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_right_hand_side(hp::StaticMappingQ1<dim,spacedim>::mapping_collection,
- dof_handler, quadrature,
- rhs_function, rhs_vector);
-}
+ template <int dim, int spacedim>
+ void create_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const hp::QCollection<dim> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ create_right_hand_side(hp::StaticMappingQ1<dim,spacedim>::mapping_collection,
+ dof_handler, quadrature,
+ rhs_function, rhs_vector);
+ }
-template <int dim, int spacedim>
-void VectorTools::create_point_source_vector (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof_handler,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector)
-{
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- Assert (dof_handler.get_fe().n_components() == 1,
- ExcMessage ("This function only works for scalar finite elements"));
+ template <int dim, int spacedim>
+ void create_point_source_vector (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof_handler,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector)
+ {
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
+ Assert (dof_handler.get_fe().n_components() == 1,
+ ExcMessage ("This function only works for scalar finite elements"));
- rhs_vector = 0;
+ rhs_vector = 0;
- std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
cell_point =
GridTools::find_active_cell_around_point (mapping, dof_handler, p);
- Quadrature<dim> q(GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
+ Quadrature<dim> q(GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
- FEValues<dim,spacedim> fe_values(mapping, dof_handler.get_fe(),
- q, UpdateFlags(update_values));
- fe_values.reinit(cell_point.first);
+ FEValues<dim,spacedim> fe_values(mapping, dof_handler.get_fe(),
+ q, UpdateFlags(update_values));
+ fe_values.reinit(cell_point.first);
- const unsigned int dofs_per_cell = dof_handler.get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell = dof_handler.get_fe().dofs_per_cell;
- std::vector<unsigned int> local_dof_indices (dofs_per_cell);
- cell_point.first->get_dof_indices (local_dof_indices);
+ std::vector<unsigned int> local_dof_indices (dofs_per_cell);
+ cell_point.first->get_dof_indices (local_dof_indices);
- for(unsigned int i=0; i<dofs_per_cell; i++)
+ for(unsigned int i=0; i<dofs_per_cell; i++)
rhs_vector(local_dof_indices[i]) = fe_values.shape_value(i,0);
-}
+ }
-template <int dim, int spacedim>
-void VectorTools::create_point_source_vector (const DoFHandler<dim,spacedim> &dof_handler,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_point_source_vector(StaticMappingQ1<dim,spacedim>::mapping, dof_handler,
- p, rhs_vector);
-}
+ template <int dim, int spacedim>
+ void create_point_source_vector (const DoFHandler<dim,spacedim> &dof_handler,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ create_point_source_vector(StaticMappingQ1<dim,spacedim>::mapping, dof_handler,
+ p, rhs_vector);
+ }
-template <int dim, int spacedim>
-void VectorTools::create_point_source_vector (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof_handler,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector)
-{
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- Assert (dof_handler.get_fe().n_components() == 1,
- ExcMessage ("This function only works for scalar finite elements"));
+ template <int dim, int spacedim>
+ void create_point_source_vector (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector)
+ {
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
+ Assert (dof_handler.get_fe().n_components() == 1,
+ ExcMessage ("This function only works for scalar finite elements"));
- rhs_vector = 0;
+ rhs_vector = 0;
- std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
cell_point =
GridTools::find_active_cell_around_point (mapping, dof_handler, p);
- Quadrature<dim> q(GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
+ Quadrature<dim> q(GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
- FEValues<dim> fe_values(mapping[cell_point.first->active_fe_index()],
- cell_point.first->get_fe(), q, UpdateFlags(update_values));
- fe_values.reinit(cell_point.first);
+ FEValues<dim> fe_values(mapping[cell_point.first->active_fe_index()],
+ cell_point.first->get_fe(), q, UpdateFlags(update_values));
+ fe_values.reinit(cell_point.first);
- const unsigned int dofs_per_cell = cell_point.first->get_fe().dofs_per_cell;
+ const unsigned int dofs_per_cell = cell_point.first->get_fe().dofs_per_cell;
- std::vector<unsigned int> local_dof_indices (dofs_per_cell);
- cell_point.first->get_dof_indices (local_dof_indices);
+ std::vector<unsigned int> local_dof_indices (dofs_per_cell);
+ cell_point.first->get_dof_indices (local_dof_indices);
- for(unsigned int i=0; i<dofs_per_cell; i++)
+ for(unsigned int i=0; i<dofs_per_cell; i++)
rhs_vector(local_dof_indices[i]) = fe_values.shape_value(i,0);
-}
+ }
-template <int dim, int spacedim>
-void VectorTools::create_point_source_vector (const hp::DoFHandler<dim,spacedim> &dof_handler,
- const Point<spacedim> &p,
- Vector<double> &rhs_vector)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_point_source_vector(hp::StaticMappingQ1<dim>::mapping_collection,
- dof_handler,
- p, rhs_vector);
-}
+ template <int dim, int spacedim>
+ void create_point_source_vector (const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const Point<spacedim> &p,
+ Vector<double> &rhs_vector)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ create_point_source_vector(hp::StaticMappingQ1<dim>::mapping_collection,
+ dof_handler,
+ p, rhs_vector);
+ }
// separate implementation for 1D because otherwise we get linker errors since
// FEFaceValues<1> is not compiled
-template <>
-void
-VectorTools::create_boundary_right_hand_side (const Mapping<1,1> &,
- const DoFHandler<1,1> &,
- const Quadrature<0> &,
- const Function<1> &,
- Vector<double> &,
- const std::set<unsigned char> &)
-{
- Assert (false, ExcImpossibleInDim(1));
-}
-
-
+ template <>
+ void
+ create_boundary_right_hand_side (const Mapping<1,1> &,
+ const DoFHandler<1,1> &,
+ const Quadrature<0> &,
+ const Function<1> &,
+ Vector<double> &,
+ const std::set<unsigned char> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
-template <>
-void
-VectorTools::create_boundary_right_hand_side (const Mapping<1,2> &,
- const DoFHandler<1,2> &,
- const Quadrature<0> &,
- const Function<2> &,
- Vector<double> &,
- const std::set<unsigned char> &)
-{
- Assert (false, ExcImpossibleInDim(1));
-}
+ template <>
+ void
+ create_boundary_right_hand_side (const Mapping<1,2> &,
+ const DoFHandler<1,2> &,
+ const Quadrature<0> &,
+ const Function<2> &,
+ Vector<double> &,
+ const std::set<unsigned char> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
-template <int dim, int spacedim>
-void
-VectorTools::create_boundary_right_hand_side (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof_handler,
- const Quadrature<dim-1> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators)
-{
- const FiniteElement<dim> &fe = dof_handler.get_fe();
- Assert (fe.n_components() == rhs_function.n_components,
- ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- rhs_vector = 0;
- UpdateFlags update_flags = UpdateFlags(update_values |
- update_quadrature_points |
- update_JxW_values);
- FEFaceValues<dim> fe_values (mapping, fe, quadrature, update_flags);
+ template <int dim, int spacedim>
+ void
+ create_boundary_right_hand_side (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof_handler,
+ const Quadrature<dim-1> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators)
+ {
+ const FiniteElement<dim> &fe = dof_handler.get_fe();
+ Assert (fe.n_components() == rhs_function.n_components,
+ ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points,
- n_components = fe.n_components();
+ rhs_vector = 0;
- std::vector<unsigned int> dofs (dofs_per_cell);
- Vector<double> cell_vector (dofs_per_cell);
+ UpdateFlags update_flags = UpdateFlags(update_values |
+ update_quadrature_points |
+ update_JxW_values);
+ FEFaceValues<dim> fe_values (mapping, fe, quadrature, update_flags);
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active(),
- endc = dof_handler.end();
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points,
+ n_components = fe.n_components();
- if (n_components==1)
- {
- std::vector<double> rhs_values(n_q_points);
+ std::vector<unsigned int> dofs (dofs_per_cell);
+ Vector<double> cell_vector (dofs_per_cell);
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary () &&
- (boundary_indicators.empty() ||
- (boundary_indicators.find (cell->face(face)->boundary_indicator())
- !=
- boundary_indicators.end())))
- {
- fe_values.reinit(cell, face);
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.value_list (fe_values.get_quadrature_points(), rhs_values);
+ if (n_components==1)
+ {
+ std::vector<double> rhs_values(n_q_points);
+
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary () &&
+ (boundary_indicators.empty() ||
+ (boundary_indicators.find (cell->face(face)->boundary_indicator())
+ !=
+ boundary_indicators.end())))
+ {
+ fe_values.reinit(cell, face);
- cell_vector = 0;
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_vector(i) += rhs_values[point] *
- fe_values.shape_value(i,point) *
- weights[point];
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.value_list (fe_values.get_quadrature_points(), rhs_values);
- cell->get_dof_indices (dofs);
+ cell_vector = 0;
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_vector(i) += rhs_values[point] *
+ fe_values.shape_value(i,point) *
+ weights[point];
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
- else
- {
- std::vector<Vector<double> > rhs_values(n_q_points, Vector<double>(n_components));
+ cell->get_dof_indices (dofs);
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary () &&
- (boundary_indicators.empty() ||
- (boundary_indicators.find (cell->face(face)->boundary_indicator())
- !=
- boundary_indicators.end())))
- {
- fe_values.reinit(cell, face);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ else
+ {
+ std::vector<Vector<double> > rhs_values(n_q_points, Vector<double>(n_components));
+
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary () &&
+ (boundary_indicators.empty() ||
+ (boundary_indicators.find (cell->face(face)->boundary_indicator())
+ !=
+ boundary_indicators.end())))
+ {
+ fe_values.reinit(cell, face);
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.vector_value_list (fe_values.get_quadrature_points(), rhs_values);
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.vector_value_list (fe_values.get_quadrature_points(), rhs_values);
- cell_vector = 0;
+ cell_vector = 0;
- // Use the faster code if the
- // FiniteElement is primitive
- if (fe.is_primitive ())
- {
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- const unsigned int component
- = fe.system_to_component_index(i).first;
+ // Use the faster code if the
+ // FiniteElement is primitive
+ if (fe.is_primitive ())
+ {
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ const unsigned int component
+ = fe.system_to_component_index(i).first;
- cell_vector(i) += rhs_values[point](component) *
- fe_values.shape_value(i,point) *
- weights[point];
- }
- }
- else
- {
- // And the full featured
- // code, if vector valued
- // FEs are used
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
- if (fe.get_nonzero_components(i)[comp_i])
- {
- cell_vector(i)
- += rhs_values[point](comp_i) *
- fe_values.shape_value_component(i,point,comp_i) *
- weights[point];
- }
- }
+ cell_vector(i) += rhs_values[point](component) *
+ fe_values.shape_value(i,point) *
+ weights[point];
+ }
+ }
+ else
+ {
+ // And the full featured
+ // code, if vector valued
+ // FEs are used
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
+ if (fe.get_nonzero_components(i)[comp_i])
+ {
+ cell_vector(i)
+ += rhs_values[point](comp_i) *
+ fe_values.shape_value_component(i,point,comp_i) *
+ weights[point];
+ }
+ }
- cell->get_dof_indices (dofs);
+ cell->get_dof_indices (dofs);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
-}
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ }
-template <int dim, int spacedim>
-void
-VectorTools::create_boundary_right_hand_side (const DoFHandler<dim,spacedim> &dof_handler,
- const Quadrature<dim-1> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ template <int dim, int spacedim>
+ void
+ create_boundary_right_hand_side (const DoFHandler<dim,spacedim> &dof_handler,
+ const Quadrature<dim-1> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_boundary_right_hand_side(StaticMappingQ1<dim>::mapping, dof_handler,
- quadrature,
- rhs_function, rhs_vector,
- boundary_indicators);
-}
+ create_boundary_right_hand_side(StaticMappingQ1<dim>::mapping, dof_handler,
+ quadrature,
+ rhs_function, rhs_vector,
+ boundary_indicators);
+ }
// separate implementation for 1D because otherwise we get linker errors since
// hp::FEFaceValues<1> is not compiled
-template <>
-void
-VectorTools::create_boundary_right_hand_side (const hp::MappingCollection<1,1> &,
- const hp::DoFHandler<1,1> &,
- const hp::QCollection<0> &,
- const Function<1> &,
- Vector<double> &,
- const std::set<unsigned char> &)
-{
- Assert (false, ExcImpossibleInDim(1));
-}
-
-
+ template <>
+ void
+ create_boundary_right_hand_side (const hp::MappingCollection<1,1> &,
+ const hp::DoFHandler<1,1> &,
+ const hp::QCollection<0> &,
+ const Function<1> &,
+ Vector<double> &,
+ const std::set<unsigned char> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
-template <>
-void
-VectorTools::create_boundary_right_hand_side (const hp::MappingCollection<1,2> &,
- const hp::DoFHandler<1,2> &,
- const hp::QCollection<0> &,
- const Function<2> &,
- Vector<double> &,
- const std::set<unsigned char> &)
-{
- Assert (false, ExcImpossibleInDim(1));
-}
+ template <>
+ void
+ create_boundary_right_hand_side (const hp::MappingCollection<1,2> &,
+ const hp::DoFHandler<1,2> &,
+ const hp::QCollection<0> &,
+ const Function<2> &,
+ Vector<double> &,
+ const std::set<unsigned char> &)
+ {
+ Assert (false, ExcImpossibleInDim(1));
+ }
-template <int dim, int spacedim>
-void
-VectorTools::create_boundary_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &dof_handler,
- const hp::QCollection<dim-1> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators)
-{
- const hp::FECollection<dim> &fe = dof_handler.get_fe();
- Assert (fe.n_components() == rhs_function.n_components,
- ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
- Assert (rhs_vector.size() == dof_handler.n_dofs(),
- ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- rhs_vector = 0;
- UpdateFlags update_flags = UpdateFlags(update_values |
- update_quadrature_points |
- update_JxW_values);
- hp::FEFaceValues<dim> x_fe_values (mapping, fe, quadrature, update_flags);
+ template <int dim, int spacedim>
+ void
+ create_boundary_right_hand_side (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const hp::QCollection<dim-1> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators)
+ {
+ const hp::FECollection<dim> &fe = dof_handler.get_fe();
+ Assert (fe.n_components() == rhs_function.n_components,
+ ExcDimensionMismatch(fe.n_components(), rhs_function.n_components));
+ Assert (rhs_vector.size() == dof_handler.n_dofs(),
+ ExcDimensionMismatch(rhs_vector.size(), dof_handler.n_dofs()));
- const unsigned int n_components = fe.n_components();
+ rhs_vector = 0;
- std::vector<unsigned int> dofs (fe.max_dofs_per_cell());
- Vector<double> cell_vector (fe.max_dofs_per_cell());
+ UpdateFlags update_flags = UpdateFlags(update_values |
+ update_quadrature_points |
+ update_JxW_values);
+ hp::FEFaceValues<dim> x_fe_values (mapping, fe, quadrature, update_flags);
- typename hp::DoFHandler<dim,spacedim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
+ const unsigned int n_components = fe.n_components();
- if (n_components==1)
- {
- std::vector<double> rhs_values;
+ std::vector<unsigned int> dofs (fe.max_dofs_per_cell());
+ Vector<double> cell_vector (fe.max_dofs_per_cell());
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary () &&
- (boundary_indicators.empty() ||
- (boundary_indicators.find (cell->face(face)->boundary_indicator())
- !=
- boundary_indicators.end())))
- {
- x_fe_values.reinit(cell, face);
+ typename hp::DoFHandler<dim,spacedim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
- const FEFaceValues<dim> &fe_values = x_fe_values.get_present_fe_values();
+ if (n_components==1)
+ {
+ std::vector<double> rhs_values;
+
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary () &&
+ (boundary_indicators.empty() ||
+ (boundary_indicators.find (cell->face(face)->boundary_indicator())
+ !=
+ boundary_indicators.end())))
+ {
+ x_fe_values.reinit(cell, face);
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points;
- rhs_values.resize (n_q_points);
+ const FEFaceValues<dim> &fe_values = x_fe_values.get_present_fe_values();
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.value_list (fe_values.get_quadrature_points(), rhs_values);
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points;
+ rhs_values.resize (n_q_points);
- cell_vector = 0;
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- cell_vector(i) += rhs_values[point] *
- fe_values.shape_value(i,point) *
- weights[point];
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.value_list (fe_values.get_quadrature_points(), rhs_values);
- dofs.resize(dofs_per_cell);
- cell->get_dof_indices (dofs);
+ cell_vector = 0;
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ cell_vector(i) += rhs_values[point] *
+ fe_values.shape_value(i,point) *
+ weights[point];
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
- else
- {
- std::vector<Vector<double> > rhs_values;
+ dofs.resize(dofs_per_cell);
+ cell->get_dof_indices (dofs);
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary () &&
- (boundary_indicators.empty() ||
- (boundary_indicators.find (cell->face(face)->boundary_indicator())
- !=
- boundary_indicators.end())))
- {
- x_fe_values.reinit(cell, face);
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ else
+ {
+ std::vector<Vector<double> > rhs_values;
+
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary () &&
+ (boundary_indicators.empty() ||
+ (boundary_indicators.find (cell->face(face)->boundary_indicator())
+ !=
+ boundary_indicators.end())))
+ {
+ x_fe_values.reinit(cell, face);
- const FEFaceValues<dim> &fe_values = x_fe_values.get_present_fe_values();
+ const FEFaceValues<dim> &fe_values = x_fe_values.get_present_fe_values();
- const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
- n_q_points = fe_values.n_quadrature_points;
- rhs_values.resize (n_q_points, Vector<double>(n_components));
+ const unsigned int dofs_per_cell = fe_values.dofs_per_cell,
+ n_q_points = fe_values.n_quadrature_points;
+ rhs_values.resize (n_q_points, Vector<double>(n_components));
- const std::vector<double> &weights = fe_values.get_JxW_values ();
- rhs_function.vector_value_list (fe_values.get_quadrature_points(), rhs_values);
+ const std::vector<double> &weights = fe_values.get_JxW_values ();
+ rhs_function.vector_value_list (fe_values.get_quadrature_points(), rhs_values);
- cell_vector = 0;
+ cell_vector = 0;
- // Use the faster code if the
- // FiniteElement is primitive
- if (cell->get_fe().is_primitive ())
- {
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- const unsigned int component
- = cell->get_fe().system_to_component_index(i).first;
+ // Use the faster code if the
+ // FiniteElement is primitive
+ if (cell->get_fe().is_primitive ())
+ {
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ const unsigned int component
+ = cell->get_fe().system_to_component_index(i).first;
- cell_vector(i) += rhs_values[point](component) *
- fe_values.shape_value(i,point) *
- weights[point];
- }
- }
- else
- {
- // And the full featured
- // code, if vector valued
- // FEs are used
- for (unsigned int point=0; point<n_q_points; ++point)
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
- if (cell->get_fe().get_nonzero_components(i)[comp_i])
- {
- cell_vector(i)
- += rhs_values[point](comp_i) *
- fe_values.shape_value_component(i,point,comp_i) *
- weights[point];
- }
- }
- dofs.resize(dofs_per_cell);
- cell->get_dof_indices (dofs);
+ cell_vector(i) += rhs_values[point](component) *
+ fe_values.shape_value(i,point) *
+ weights[point];
+ }
+ }
+ else
+ {
+ // And the full featured
+ // code, if vector valued
+ // FEs are used
+ for (unsigned int point=0; point<n_q_points; ++point)
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int comp_i = 0; comp_i < n_components; ++comp_i)
+ if (cell->get_fe().get_nonzero_components(i)[comp_i])
+ {
+ cell_vector(i)
+ += rhs_values[point](comp_i) *
+ fe_values.shape_value_component(i,point,comp_i) *
+ weights[point];
+ }
+ }
+ dofs.resize(dofs_per_cell);
+ cell->get_dof_indices (dofs);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- rhs_vector(dofs[i]) += cell_vector(i);
- }
- }
-}
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ rhs_vector(dofs[i]) += cell_vector(i);
+ }
+ }
+ }
-template <int dim, int spacedim>
-void
-VectorTools::create_boundary_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof_handler,
- const hp::QCollection<dim-1> &quadrature,
- const Function<spacedim> &rhs_function,
- Vector<double> &rhs_vector,
- const std::set<unsigned char> &boundary_indicators)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- create_boundary_right_hand_side(hp::StaticMappingQ1<dim>::mapping_collection,
- dof_handler, quadrature,
- rhs_function, rhs_vector,
- boundary_indicators);
-}
+ template <int dim, int spacedim>
+ void
+ create_boundary_right_hand_side (const hp::DoFHandler<dim,spacedim> &dof_handler,
+ const hp::QCollection<dim-1> &quadrature,
+ const Function<spacedim> &rhs_function,
+ Vector<double> &rhs_vector,
+ const std::set<unsigned char> &boundary_indicators)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ create_boundary_right_hand_side(hp::StaticMappingQ1<dim>::mapping_collection,
+ dof_handler, quadrature,
+ rhs_function, rhs_vector,
+ boundary_indicators);
+ }
// ----------- interpolate_boundary_values for std::map --------------------
-namespace internal
-{
- namespace VectorTools
+ namespace internal
{
// interpolate boundary values in
// 1d. in higher dimensions, we
const typename FunctionMap<DH::space_dimension>::type &function_map,
std::map<unsigned int,double> &boundary_values,
const std::vector<bool> &component_mask_,
- const internal::int2type<1>)
+ const dealii::internal::int2type<1>)
{
const unsigned int dim = DH::dimension;
const unsigned int spacedim=DH::space_dimension;
"zero or equal to the number of components in the finite "
"element."));
- // if for whatever reason we were
- // passed an empty map, return
- // immediately
+ // if for whatever reason we were
+ // passed an empty map, return
+ // immediately
if (function_map.size() == 0)
return;
for (typename FunctionMap<spacedim>::type::const_iterator i=function_map.begin();
i!=function_map.end(); ++i)
Assert (i->first < 2,
- dealii::VectorTools::ExcInvalidBoundaryIndicator());
+ ExcInvalidBoundaryIndicator());
for (typename DH::active_cell_iterator cell = dof.begin_active();
cell != dof.end(); ++cell)
std::vector<bool> (fe.n_components(), true) :
component_mask_);
Assert (std::count(component_mask.begin(), component_mask.end(), true) > 0,
- dealii::VectorTools::ExcNoComponentSelected());
+ ExcNoComponentSelected());
// now set the value of
// the vertex degree of
const typename FunctionMap<DH::space_dimension>::type &function_map,
std::map<unsigned int,double> &boundary_values,
const std::vector<bool> &component_mask_,
- const internal::int2type<DH::dimension>)
+ const dealii::internal::int2type<DH::dimension>)
{
const unsigned int dim = DH::dimension;
const unsigned int spacedim=DH::space_dimension;
"element."));
- // if for whatever reason we were
- // passed an empty map, return
- // immediately
+ // if for whatever reason we were
+ // passed an empty map, return
+ // immediately
if (function_map.size() == 0)
return;
Assert (function_map.find(255) == function_map.end(),
- dealii::VectorTools::ExcInvalidBoundaryIndicator());
+ ExcInvalidBoundaryIndicator());
const unsigned int n_components = DoFTools::n_components(dof);
const bool fe_is_system = (n_components != 1);
Assert (n_components == i->second->n_components,
ExcDimensionMismatch(n_components, i->second->n_components));
- // set the component mask to either
- // the original value or a vector
- // of trues
+ // set the component mask to either
+ // the original value or a vector
+ // of trues
const std::vector<bool> component_mask ((component_mask_.size() == 0) ?
std::vector<bool> (n_components, true) :
component_mask_);
Assert (std::count(component_mask.begin(), component_mask.end(), true) > 0,
- dealii::VectorTools::ExcNoComponentSelected());
+ ExcNoComponentSelected());
- // field to store the indices
+ // field to store the indices
std::vector<unsigned int> face_dofs;
face_dofs.reserve (DoFTools::max_dofs_per_face(dof));
std::vector<Point<spacedim> > dof_locations;
dof_locations.reserve (DoFTools::max_dofs_per_face(dof));
- // array to store the values of
- // the boundary function at the
- // boundary points. have two arrays
- // for scalar and vector functions
- // to use the more efficient one
- // respectively
+ // array to store the values of
+ // the boundary function at the
+ // boundary points. have two arrays
+ // for scalar and vector functions
+ // to use the more efficient one
+ // respectively
std::vector<double> dof_values_scalar;
std::vector<dealii::Vector<double> > dof_values_system;
dof_values_scalar.reserve (DoFTools::max_dofs_per_face (dof));
dof_values_system.reserve (DoFTools::max_dofs_per_face (dof));
- // before we start with the loop
- // over all cells create an
- // hp::FEValues object that holds
- // the interpolation points of all
- // finite elements that may ever be
- // in use
+ // before we start with the loop
+ // over all cells create an
+ // hp::FEValues object that holds
+ // the interpolation points of all
+ // finite elements that may ever be
+ // in use
dealii::hp::FECollection<dim,spacedim> finite_elements (dof.get_fe());
dealii::hp::QCollection<dim-1> q_collection;
for (unsigned int f=0; f<finite_elements.size(); ++f)
- {
- const FiniteElement<dim,spacedim> &fe = finite_elements[f];
-
- // generate a quadrature rule
- // on the face from the unit
- // support points. this will be
- // used to obtain the
- // quadrature points on the
- // real cell's face
- //
- // to do this, we check whether
- // the FE has support points on
- // the face at all:
- if (fe.has_face_support_points())
- q_collection.push_back (Quadrature<dim-1>(fe.get_unit_face_support_points()));
- else
{
- // if not, then we should
- // try a more clever
- // way. the idea is that a
- // finite element may not
- // offer support points for
- // all its shape functions,
- // but maybe only some. if
- // it offers support points
- // for the components we
- // are interested in in
- // this function, then
- // that's fine. if not, the
- // function we call in the
- // finite element will
- // raise an exception. the
- // support points for the
- // other shape functions
- // are left uninitialized
- // (well, initialized by
- // the default
- // constructor), since we
- // don't need them anyway.
+ const FiniteElement<dim,spacedim> &fe = finite_elements[f];
+
+ // generate a quadrature rule
+ // on the face from the unit
+ // support points. this will be
+ // used to obtain the
+ // quadrature points on the
+ // real cell's face
//
- // As a detour, we must
- // make sure we only query
- // face_system_to_component_index
- // if the index corresponds
- // to a primitive shape
- // function. since we know
- // that all the components
- // we are interested in are
- // primitive (by the above
- // check), we can safely
- // put such a check in
- // front
- std::vector<Point<dim-1> > unit_support_points (fe.dofs_per_face);
-
- for (unsigned int i=0; i<fe.dofs_per_face; ++i)
- if (fe.is_primitive (fe.face_to_equivalent_cell_index(i)))
- if (component_mask[fe.face_system_to_component_index(i).first]
- == true)
- unit_support_points[i] = fe.unit_face_support_point(i);
-
- q_collection.push_back (Quadrature<dim-1>(unit_support_points));
- }
- }
- // now that we have a q_collection
- // object with all the right
- // quadrature points, create an
- // hp::FEFaceValues object that we
- // can use to evaluate the boundary
- // values at
+ // to do this, we check whether
+ // the FE has support points on
+ // the face at all:
+ if (fe.has_face_support_points())
+ q_collection.push_back (Quadrature<dim-1>(fe.get_unit_face_support_points()));
+ else
+ {
+ // if not, then we should
+ // try a more clever
+ // way. the idea is that a
+ // finite element may not
+ // offer support points for
+ // all its shape functions,
+ // but maybe only some. if
+ // it offers support points
+ // for the components we
+ // are interested in in
+ // this function, then
+ // that's fine. if not, the
+ // function we call in the
+ // finite element will
+ // raise an exception. the
+ // support points for the
+ // other shape functions
+ // are left uninitialized
+ // (well, initialized by
+ // the default
+ // constructor), since we
+ // don't need them anyway.
+ //
+ // As a detour, we must
+ // make sure we only query
+ // face_system_to_component_index
+ // if the index corresponds
+ // to a primitive shape
+ // function. since we know
+ // that all the components
+ // we are interested in are
+ // primitive (by the above
+ // check), we can safely
+ // put such a check in
+ // front
+ std::vector<Point<dim-1> > unit_support_points (fe.dofs_per_face);
+
+ for (unsigned int i=0; i<fe.dofs_per_face; ++i)
+ if (fe.is_primitive (fe.face_to_equivalent_cell_index(i)))
+ if (component_mask[fe.face_system_to_component_index(i).first]
+ == true)
+ unit_support_points[i] = fe.unit_face_support_point(i);
+
+ q_collection.push_back (Quadrature<dim-1>(unit_support_points));
+ }
+ }
+ // now that we have a q_collection
+ // object with all the right
+ // quadrature points, create an
+ // hp::FEFaceValues object that we
+ // can use to evaluate the boundary
+ // values at
dealii::hp::MappingCollection<dim,spacedim> mapping_collection (mapping);
dealii::hp::FEFaceValues<dim,spacedim> x_fe_values (mapping_collection, finite_elements, q_collection,
- update_quadrature_points);
+ update_quadrature_points);
typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
+ endc = dof.end();
for (; cell!=endc; ++cell)
if (!cell->is_artificial())
- for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
- ++face_no)
- {
- const FiniteElement<dim,spacedim> &fe = cell->get_fe();
-
- // we can presently deal only with
- // primitive elements for boundary
- // values. this does not preclude
- // us using non-primitive elements
- // in components that we aren't
- // interested in, however. make
- // sure that all shape functions
- // that are non-zero for the
- // components we are interested in,
- // are in fact primitive
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
{
- const std::vector<bool> &nonzero_component_array
- = cell->get_fe().get_nonzero_components (i);
- for (unsigned int c=0; c<n_components; ++c)
- if ((nonzero_component_array[c] == true)
- &&
- (component_mask[c] == true))
- Assert (cell->get_fe().is_primitive (i),
- ExcMessage ("This function can only deal with requested boundary "
- "values that correspond to primitive (scalar) base "
- "elements"));
- }
+ const FiniteElement<dim,spacedim> &fe = cell->get_fe();
- typename DH::face_iterator face = cell->face(face_no);
+ // we can presently deal only with
+ // primitive elements for boundary
+ // values. this does not preclude
+ // us using non-primitive elements
+ // in components that we aren't
+ // interested in, however. make
+ // sure that all shape functions
+ // that are non-zero for the
+ // components we are interested in,
+ // are in fact primitive
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ {
+ const std::vector<bool> &nonzero_component_array
+ = cell->get_fe().get_nonzero_components (i);
+ for (unsigned int c=0; c<n_components; ++c)
+ if ((nonzero_component_array[c] == true)
+ &&
+ (component_mask[c] == true))
+ Assert (cell->get_fe().is_primitive (i),
+ ExcMessage ("This function can only deal with requested boundary "
+ "values that correspond to primitive (scalar) base "
+ "elements"));
+ }
- // cast the face iterator to a DoFHandler
- // iterator so that we can access the boundary
- // indicators
- const unsigned char boundary_component = face->boundary_indicator();
- if (function_map.find(boundary_component) != function_map.end())
- {
- // face is of the right component
- x_fe_values.reinit(cell, face_no);
- const dealii::FEFaceValues<dim,spacedim> &fe_values =
- x_fe_values.get_present_fe_values();
-
- // get indices, physical location and
- // boundary values of dofs on this
- // face
- face_dofs.resize (fe.dofs_per_face);
- face->get_dof_indices (face_dofs, cell->active_fe_index());
- const std::vector<Point<spacedim> > &dof_locations
- = fe_values.get_quadrature_points ();
+ typename DH::face_iterator face = cell->face(face_no);
- if (fe_is_system)
+ // cast the face iterator to a DoFHandler
+ // iterator so that we can access the boundary
+ // indicators
+ const unsigned char boundary_component = face->boundary_indicator();
+ if (function_map.find(boundary_component) != function_map.end())
{
- // resize
- // array. avoid
- // construction of a
- // memory allocating
- // temporary if
- // possible
- if (dof_values_system.size() < fe.dofs_per_face)
- dof_values_system.resize (fe.dofs_per_face,
- dealii::Vector<double>(fe.n_components()));
- else
- dof_values_system.resize (fe.dofs_per_face);
-
- function_map.find(boundary_component)->second
- ->vector_value_list (dof_locations, dof_values_system);
-
- // enter those dofs
- // into the list that
- // match the
- // component
- // signature. avoid
- // the usual
- // complication that
- // we can't just use
- // *_system_to_component_index
- // for non-primitive
- // FEs
- for (unsigned int i=0; i<face_dofs.size(); ++i)
+ // face is of the right component
+ x_fe_values.reinit(cell, face_no);
+ const dealii::FEFaceValues<dim,spacedim> &fe_values =
+ x_fe_values.get_present_fe_values();
+
+ // get indices, physical location and
+ // boundary values of dofs on this
+ // face
+ face_dofs.resize (fe.dofs_per_face);
+ face->get_dof_indices (face_dofs, cell->active_fe_index());
+ const std::vector<Point<spacedim> > &dof_locations
+ = fe_values.get_quadrature_points ();
+
+ if (fe_is_system)
{
- unsigned int component;
- if (fe.is_primitive())
- component = fe.face_system_to_component_index(i).first;
+ // resize
+ // array. avoid
+ // construction of a
+ // memory allocating
+ // temporary if
+ // possible
+ if (dof_values_system.size() < fe.dofs_per_face)
+ dof_values_system.resize (fe.dofs_per_face,
+ dealii::Vector<double>(fe.n_components()));
else
+ dof_values_system.resize (fe.dofs_per_face);
+
+ function_map.find(boundary_component)->second
+ ->vector_value_list (dof_locations, dof_values_system);
+
+ // enter those dofs
+ // into the list that
+ // match the
+ // component
+ // signature. avoid
+ // the usual
+ // complication that
+ // we can't just use
+ // *_system_to_component_index
+ // for non-primitive
+ // FEs
+ for (unsigned int i=0; i<face_dofs.size(); ++i)
{
- // non-primitive
- // case. make
- // sure that
- // this
- // particular
- // shape
- // function
- // _is_
- // primitive,
- // and get at
- // it's
- // component. use
- // usual
- // trick to
- // transfer
- // face dof
- // index to
- // cell dof
- // index
- const unsigned int cell_i
- = (dim == 1 ?
- i
- :
- (dim == 2 ?
- (i<2*fe.dofs_per_vertex ? i : i+2*fe.dofs_per_vertex)
- :
- (dim == 3 ?
- (i<4*fe.dofs_per_vertex ?
- i
- :
- (i<4*fe.dofs_per_vertex+4*fe.dofs_per_line ?
- i+4*fe.dofs_per_vertex
+ unsigned int component;
+ if (fe.is_primitive())
+ component = fe.face_system_to_component_index(i).first;
+ else
+ {
+ // non-primitive
+ // case. make
+ // sure that
+ // this
+ // particular
+ // shape
+ // function
+ // _is_
+ // primitive,
+ // and get at
+ // it's
+ // component. use
+ // usual
+ // trick to
+ // transfer
+ // face dof
+ // index to
+ // cell dof
+ // index
+ const unsigned int cell_i
+ = (dim == 1 ?
+ i
:
- i+4*fe.dofs_per_vertex+8*fe.dofs_per_line))
- :
- numbers::invalid_unsigned_int)));
- Assert (cell_i < fe.dofs_per_cell, ExcInternalError());
-
- // make sure
- // that if
- // this is
- // not a
- // primitive
- // shape function,
- // then all
- // the
- // corresponding
- // components
- // in the
- // mask are
- // not set
- if (!fe.is_primitive(cell_i))
- for (unsigned int c=0; c<n_components; ++c)
- if (fe.get_nonzero_components(cell_i)[c])
- Assert (component_mask[c] == false,
- FETools::ExcFENotPrimitive());
-
- // let's pick
- // the first
- // of
- // possibly
- // more than
- // one
- // non-zero
- // components. if
- // shape
- // function
- // is
- // non-primitive,
- // then we
- // will
- // ignore the
- // result in
- // the
- // following
- // anyway,
- // otherwise
- // there's
- // only one
- // non-zero
- // component
- // which we
- // will use
- component = (std::find (fe.get_nonzero_components(cell_i).begin(),
- fe.get_nonzero_components(cell_i).end(),
- true)
- -
- fe.get_nonzero_components(cell_i).begin());
+ (dim == 2 ?
+ (i<2*fe.dofs_per_vertex ? i : i+2*fe.dofs_per_vertex)
+ :
+ (dim == 3 ?
+ (i<4*fe.dofs_per_vertex ?
+ i
+ :
+ (i<4*fe.dofs_per_vertex+4*fe.dofs_per_line ?
+ i+4*fe.dofs_per_vertex
+ :
+ i+4*fe.dofs_per_vertex+8*fe.dofs_per_line))
+ :
+ numbers::invalid_unsigned_int)));
+ Assert (cell_i < fe.dofs_per_cell, ExcInternalError());
+
+ // make sure
+ // that if
+ // this is
+ // not a
+ // primitive
+ // shape function,
+ // then all
+ // the
+ // corresponding
+ // components
+ // in the
+ // mask are
+ // not set
+ if (!fe.is_primitive(cell_i))
+ for (unsigned int c=0; c<n_components; ++c)
+ if (fe.get_nonzero_components(cell_i)[c])
+ Assert (component_mask[c] == false,
+ FETools::ExcFENotPrimitive());
+
+ // let's pick
+ // the first
+ // of
+ // possibly
+ // more than
+ // one
+ // non-zero
+ // components. if
+ // shape
+ // function
+ // is
+ // non-primitive,
+ // then we
+ // will
+ // ignore the
+ // result in
+ // the
+ // following
+ // anyway,
+ // otherwise
+ // there's
+ // only one
+ // non-zero
+ // component
+ // which we
+ // will use
+ component = (std::find (fe.get_nonzero_components(cell_i).begin(),
+ fe.get_nonzero_components(cell_i).end(),
+ true)
+ -
+ fe.get_nonzero_components(cell_i).begin());
+ }
+
+ if (component_mask[component] == true)
+ boundary_values[face_dofs[i]] = dof_values_system[i](component);
}
-
- if (component_mask[component] == true)
- boundary_values[face_dofs[i]] = dof_values_system[i](component);
}
- }
- else
- // fe has only one component,
- // so save some computations
- {
- // get only the one component that
- // this function has
- dof_values_scalar.resize (fe.dofs_per_face);
- function_map.find(boundary_component)->second
- ->value_list (dof_locations, dof_values_scalar, 0);
+ else
+ // fe has only one component,
+ // so save some computations
+ {
+ // get only the one component that
+ // this function has
+ dof_values_scalar.resize (fe.dofs_per_face);
+ function_map.find(boundary_component)->second
+ ->value_list (dof_locations, dof_values_scalar, 0);
- // enter into list
+ // enter into list
- for (unsigned int i=0; i<face_dofs.size(); ++i)
- boundary_values[face_dofs[i]] = dof_values_scalar[i];
+ for (unsigned int i=0; i<face_dofs.size(); ++i)
+ boundary_values[face_dofs[i]] = dof_values_scalar[i];
+ }
}
}
- }
} // end of interpolate_boundary_values
- } // end of namespace VectorTools
-} // end of namespace internal
+ } // end of namespace internal
-template <class DH>
-void
-VectorTools::
-interpolate_boundary_values (const Mapping<DH::dimension, DH::space_dimension> &mapping,
- const DH &dof,
- const typename FunctionMap<DH::space_dimension>::type &function_map,
- std::map<unsigned int,double> &boundary_values,
- const std::vector<bool> &component_mask_)
-{
- dealii::internal::VectorTools::
- interpolate_boundary_values (mapping, dof, function_map, boundary_values,
- component_mask_,
- dealii::internal::int2type<DH::dimension>());
-}
+ template <class DH>
+ void
+ interpolate_boundary_values (const Mapping<DH::dimension, DH::space_dimension> &mapping,
+ const DH &dof,
+ const typename FunctionMap<DH::space_dimension>::type &function_map,
+ std::map<unsigned int,double> &boundary_values,
+ const std::vector<bool> &component_mask_)
+ {
+ internal::
+ interpolate_boundary_values (mapping, dof, function_map, boundary_values,
+ component_mask_,
+ dealii::internal::int2type<DH::dimension>());
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values (const Mapping<DH::dimension, DH::space_dimension> &mapping,
- const DH &dof,
- const unsigned char boundary_component,
- const Function<DH::space_dimension> &boundary_function,
- std::map<unsigned int,double> &boundary_values,
- const std::vector<bool> &component_mask)
-{
- typename FunctionMap<DH::space_dimension>::type function_map;
- function_map[boundary_component] = &boundary_function;
- interpolate_boundary_values (mapping, dof, function_map, boundary_values,
- component_mask);
-}
+ template <class DH>
+ void
+ interpolate_boundary_values (const Mapping<DH::dimension, DH::space_dimension> &mapping,
+ const DH &dof,
+ const unsigned char boundary_component,
+ const Function<DH::space_dimension> &boundary_function,
+ std::map<unsigned int,double> &boundary_values,
+ const std::vector<bool> &component_mask)
+ {
+ typename FunctionMap<DH::space_dimension>::type function_map;
+ function_map[boundary_component] = &boundary_function;
+ interpolate_boundary_values (mapping, dof, function_map, boundary_values,
+ component_mask);
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values (const DH &dof,
- const unsigned char boundary_component,
- const Function<DH::space_dimension> &boundary_function,
- std::map<unsigned int,double> &boundary_values,
- const std::vector<bool> &component_mask)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
- dof, boundary_component,
- boundary_function, boundary_values, component_mask);
-}
+ template <class DH>
+ void
+ interpolate_boundary_values (const DH &dof,
+ const unsigned char boundary_component,
+ const Function<DH::space_dimension> &boundary_function,
+ std::map<unsigned int,double> &boundary_values,
+ const std::vector<bool> &component_mask)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
+ dof, boundary_component,
+ boundary_function, boundary_values, component_mask);
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values (const DH &dof,
- const typename FunctionMap<DH::space_dimension>::type &function_map,
- std::map<unsigned int,double> &boundary_values,
- const std::vector<bool> &component_mask)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
- dof, function_map,
- boundary_values, component_mask);
-}
+
+ template <class DH>
+ void
+ interpolate_boundary_values (const DH &dof,
+ const typename FunctionMap<DH::space_dimension>::type &function_map,
+ std::map<unsigned int,double> &boundary_values,
+ const std::vector<bool> &component_mask)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
+ dof, function_map,
+ boundary_values, component_mask);
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values
- (const Mapping<DH::dimension, DH::space_dimension> &mapping,
- const DH &dof,
- const typename FunctionMap<DH::space_dimension>::type &function_map,
- ConstraintMatrix &constraints,
- const std::vector<bool> &component_mask_)
-{
- std::map<unsigned int,double> boundary_values;
- interpolate_boundary_values (mapping, dof, function_map,
- boundary_values, component_mask_);
- std::map<unsigned int,double>::const_iterator boundary_value =
- boundary_values.begin();
- for ( ; boundary_value !=boundary_values.end(); ++boundary_value)
- {
- if (constraints.can_store_line (boundary_value->first)
- &&
- !constraints.is_constrained(boundary_value->first))
- {
- constraints.add_line (boundary_value->first);
- constraints.set_inhomogeneity (boundary_value->first,
- boundary_value->second);
- }
- }
-}
+ template <class DH>
+ void
+ interpolate_boundary_values
+ (const Mapping<DH::dimension, DH::space_dimension> &mapping,
+ const DH &dof,
+ const typename FunctionMap<DH::space_dimension>::type &function_map,
+ ConstraintMatrix &constraints,
+ const std::vector<bool> &component_mask_)
+ {
+ std::map<unsigned int,double> boundary_values;
+ interpolate_boundary_values (mapping, dof, function_map,
+ boundary_values, component_mask_);
+ std::map<unsigned int,double>::const_iterator boundary_value =
+ boundary_values.begin();
+ for ( ; boundary_value !=boundary_values.end(); ++boundary_value)
+ {
+ if (constraints.can_store_line (boundary_value->first)
+ &&
+ !constraints.is_constrained(boundary_value->first))
+ {
+ constraints.add_line (boundary_value->first);
+ constraints.set_inhomogeneity (boundary_value->first,
+ boundary_value->second);
+ }
+ }
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values
+ template <class DH>
+ void
+ interpolate_boundary_values
(const Mapping<DH::dimension, DH::space_dimension> &mapping,
const DH &dof,
const unsigned char boundary_component,
const Function<DH::space_dimension> &boundary_function,
ConstraintMatrix &constraints,
const std::vector<bool> &component_mask)
-{
- typename FunctionMap<DH::space_dimension>::type function_map;
- function_map[boundary_component] = &boundary_function;
- interpolate_boundary_values (mapping, dof, function_map, constraints,
- component_mask);
-}
+ {
+ typename FunctionMap<DH::space_dimension>::type function_map;
+ function_map[boundary_component] = &boundary_function;
+ interpolate_boundary_values (mapping, dof, function_map, constraints,
+ component_mask);
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values
+ template <class DH>
+ void
+ interpolate_boundary_values
(const DH &dof,
const unsigned char boundary_component,
const Function<DH::space_dimension> &boundary_function,
ConstraintMatrix &constraints,
const std::vector<bool> &component_mask)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
- dof, boundary_component,
- boundary_function, constraints, component_mask);
-}
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
+ dof, boundary_component,
+ boundary_function, constraints, component_mask);
+ }
-template <class DH>
-void
-VectorTools::interpolate_boundary_values
+ template <class DH>
+ void
+ interpolate_boundary_values
(const DH &dof,
const typename FunctionMap<DH::space_dimension>::type &function_map,
ConstraintMatrix &constraints,
const std::vector<bool> &component_mask)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
- dof, function_map,
- constraints, component_mask);
-}
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ interpolate_boundary_values(StaticMappingQ1<DH::dimension,DH::space_dimension>::mapping,
+ dof, function_map,
+ constraints, component_mask);
+ }
// separate implementations for 1D because otherwise we get linking errors
// because create_boundary_mass_matrix is not compiled for 1D
-template <>
-void
-VectorTools::project_boundary_values (const Mapping<1,1> &mapping,
- const DoFHandler<1,1> &dof,
- const FunctionMap<1>::type &boundary_functions,
- const Quadrature<0> &,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping)
-{
- Assert (component_mapping.size() == 0, ExcNotImplemented());
- // projection in 1d is equivalent
- // to interpolation
- interpolate_boundary_values (mapping, dof, boundary_functions,
- boundary_values, std::vector<bool>());
-}
+ template <>
+ void
+ project_boundary_values (const Mapping<1,1> &mapping,
+ const DoFHandler<1,1> &dof,
+ const FunctionMap<1>::type &boundary_functions,
+ const Quadrature<0> &,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping)
+ {
+ Assert (component_mapping.size() == 0, ExcNotImplemented());
+ // projection in 1d is equivalent
+ // to interpolation
+ interpolate_boundary_values (mapping, dof, boundary_functions,
+ boundary_values, std::vector<bool>());
+ }
-template <>
-void
-VectorTools::project_boundary_values (const Mapping<1,2> &mapping,
- const DoFHandler<1,2> &dof,
- const FunctionMap<2>::type &boundary_functions,
- const Quadrature<0> &,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping)
-{
- Assert (component_mapping.size() == 0, ExcNotImplemented());
- // projection in 1d is equivalent
- // to interpolation
- interpolate_boundary_values (mapping, dof, boundary_functions,
- boundary_values, std::vector<bool>());
-}
+ template <>
+ void
+ project_boundary_values (const Mapping<1,2> &mapping,
+ const DoFHandler<1,2> &dof,
+ const FunctionMap<2>::type &boundary_functions,
+ const Quadrature<0> &,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping)
+ {
+ Assert (component_mapping.size() == 0, ExcNotImplemented());
+ // projection in 1d is equivalent
+ // to interpolation
+ interpolate_boundary_values (mapping, dof, boundary_functions,
+ boundary_values, std::vector<bool>());
+ }
-template <int dim, int spacedim>
-void
-VectorTools::project_boundary_values (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim, spacedim>&dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping)
-{
-//TODO:[?] In VectorTools::project_boundary_values, no condensation of sparsity
+ template <int dim, int spacedim>
+ void
+ project_boundary_values (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim, spacedim>&dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping)
+ {
+//TODO:[?] In project_boundary_values, no condensation of sparsity
// structures, matrices and right hand sides or distribution of
// solution vectors is performed. This is ok for dim<3 because then
// there are no constrained nodes on the boundary, but is not
// acceptable for higher dimensions. Fix this.
- if (component_mapping.size() == 0)
- {
- AssertDimension (dof.get_fe().n_components(), boundary_functions.begin()->second->n_components);
- // I still do not see why i
- // should create another copy
- // here
- component_mapping.resize(dof.get_fe().n_components());
- for (unsigned int i= 0 ;i < component_mapping.size() ; ++i)
- component_mapping[i] = i;
- }
- else
- AssertDimension (dof.get_fe().n_components(), component_mapping.size());
-
- std::vector<unsigned int> dof_to_boundary_mapping;
- std::set<unsigned char> selected_boundary_components;
- for (typename FunctionMap<spacedim>::type::const_iterator i=boundary_functions.begin();
- i!=boundary_functions.end(); ++i)
- selected_boundary_components.insert (i->first);
-
- DoFTools::map_dof_to_boundary_indices (dof, selected_boundary_components,
- dof_to_boundary_mapping);
-
- // Done if no degrees of freedom on
- // the boundary
- if (dof.n_boundary_dofs (boundary_functions) == 0)
- return;
- // set up sparsity structure
- SparsityPattern sparsity(dof.n_boundary_dofs (boundary_functions),
- dof.max_couplings_between_boundary_dofs());
- DoFTools::make_boundary_sparsity_pattern (dof,
- boundary_functions,
- dof_to_boundary_mapping,
- sparsity);
-
- // note: for three or more dimensions, there
- // may be constrained nodes on the boundary
- // in this case the boundary mass matrix has
- // to be condensed and the solution is to
- // be distributed afterwards, which is not
- // yet implemented. The reason for this is
- // that we cannot simply use the condense
- // family of functions, since the matrices
- // and vectors do not use the global
- // numbering but rather the boundary
- // numbering, i.e. the condense function
- // needs to use another indirection. There
- // should be not many technical problems,
- // but it needs to be implemented
- if (dim>=3)
- {
+ if (component_mapping.size() == 0)
+ {
+ AssertDimension (dof.get_fe().n_components(), boundary_functions.begin()->second->n_components);
+ // I still do not see why i
+ // should create another copy
+ // here
+ component_mapping.resize(dof.get_fe().n_components());
+ for (unsigned int i= 0 ;i < component_mapping.size() ; ++i)
+ component_mapping[i] = i;
+ }
+ else
+ AssertDimension (dof.get_fe().n_components(), component_mapping.size());
+
+ std::vector<unsigned int> dof_to_boundary_mapping;
+ std::set<unsigned char> selected_boundary_components;
+ for (typename FunctionMap<spacedim>::type::const_iterator i=boundary_functions.begin();
+ i!=boundary_functions.end(); ++i)
+ selected_boundary_components.insert (i->first);
+
+ DoFTools::map_dof_to_boundary_indices (dof, selected_boundary_components,
+ dof_to_boundary_mapping);
+
+ // Done if no degrees of freedom on
+ // the boundary
+ if (dof.n_boundary_dofs (boundary_functions) == 0)
+ return;
+ // set up sparsity structure
+ SparsityPattern sparsity(dof.n_boundary_dofs (boundary_functions),
+ dof.max_couplings_between_boundary_dofs());
+ DoFTools::make_boundary_sparsity_pattern (dof,
+ boundary_functions,
+ dof_to_boundary_mapping,
+ sparsity);
+
+ // note: for three or more dimensions, there
+ // may be constrained nodes on the boundary
+ // in this case the boundary mass matrix has
+ // to be condensed and the solution is to
+ // be distributed afterwards, which is not
+ // yet implemented. The reason for this is
+ // that we cannot simply use the condense
+ // family of functions, since the matrices
+ // and vectors do not use the global
+ // numbering but rather the boundary
+ // numbering, i.e. the condense function
+ // needs to use another indirection. There
+ // should be not many technical problems,
+ // but it needs to be implemented
+ if (dim>=3)
+ {
#ifdef DEBUG
// Assert that there are no hanging nodes at the boundary
- int level = -1;
- for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof.begin_active();
- cell != dof.end(); ++cell)
- for (unsigned int f=0;f<GeometryInfo<dim>::faces_per_cell;++f)
- {
- if (cell->at_boundary(f))
- {
- if (level == -1)
- level = cell->level();
- else
- {
- Assert (level == cell->level(), ExcNotImplemented());
- }
- }
- }
+ int level = -1;
+ for (typename DoFHandler<dim,spacedim>::active_cell_iterator cell = dof.begin_active();
+ cell != dof.end(); ++cell)
+ for (unsigned int f=0;f<GeometryInfo<dim>::faces_per_cell;++f)
+ {
+ if (cell->at_boundary(f))
+ {
+ if (level == -1)
+ level = cell->level();
+ else
+ {
+ Assert (level == cell->level(), ExcNotImplemented());
+ }
+ }
+ }
#endif
- }
- sparsity.compress();
+ }
+ sparsity.compress();
- // make mass matrix and right hand side
- SparseMatrix<double> mass_matrix(sparsity);
- Vector<double> rhs(sparsity.n_rows());
+ // make mass matrix and right hand side
+ SparseMatrix<double> mass_matrix(sparsity);
+ Vector<double> rhs(sparsity.n_rows());
- MatrixCreator::create_boundary_mass_matrix (mapping, dof, q,
- mass_matrix, boundary_functions,
- rhs, dof_to_boundary_mapping, (const Function<spacedim>*) 0,
- component_mapping);
+ MatrixCreator::create_boundary_mass_matrix (mapping, dof, q,
+ mass_matrix, boundary_functions,
+ rhs, dof_to_boundary_mapping, (const Function<spacedim>*) 0,
+ component_mapping);
- // For certain weird elements,
- // there might be degrees of
- // freedom on the boundary, but
- // their shape functions do not
- // have support there. Let's
- // eliminate them here.
+ // For certain weird elements,
+ // there might be degrees of
+ // freedom on the boundary, but
+ // their shape functions do not
+ // have support there. Let's
+ // eliminate them here.
- // The Bogner-Fox-Schmidt element
- // is an example for those.
+ // The Bogner-Fox-Schmidt element
+ // is an example for those.
//TODO: Maybe we should figure out if the element really needs this
- FilteredMatrix<Vector<double> > filtered_mass_matrix(mass_matrix, true);
- FilteredMatrix<Vector<double> > filtered_precondition;
- std::vector<bool> excluded_dofs(mass_matrix.m(), false);
+ FilteredMatrix<Vector<double> > filtered_mass_matrix(mass_matrix, true);
+ FilteredMatrix<Vector<double> > filtered_precondition;
+ std::vector<bool> excluded_dofs(mass_matrix.m(), false);
- double max_element = 0.;
- for (unsigned int i=0;i<mass_matrix.m();++i)
- if (mass_matrix.diag_element(i) > max_element)
- max_element = mass_matrix.diag_element(i);
+ double max_element = 0.;
+ for (unsigned int i=0;i<mass_matrix.m();++i)
+ if (mass_matrix.diag_element(i) > max_element)
+ max_element = mass_matrix.diag_element(i);
- for (unsigned int i=0;i<mass_matrix.m();++i)
- if (mass_matrix.diag_element(i) < 1.e-8 * max_element)
- {
- filtered_mass_matrix.add_constraint(i, 0.);
- filtered_precondition.add_constraint(i, 0.);
- mass_matrix.diag_element(i) = 1.;
- excluded_dofs[i] = true;
- }
+ for (unsigned int i=0;i<mass_matrix.m();++i)
+ if (mass_matrix.diag_element(i) < 1.e-8 * max_element)
+ {
+ filtered_mass_matrix.add_constraint(i, 0.);
+ filtered_precondition.add_constraint(i, 0.);
+ mass_matrix.diag_element(i) = 1.;
+ excluded_dofs[i] = true;
+ }
- Vector<double> boundary_projection (rhs.size());
-
- // Allow for a maximum of 5*n
- // steps to reduce the residual by
- // 10^-12. n steps may not be
- // sufficient, since roundoff
- // errors may accumulate for badly
- // conditioned matrices
- ReductionControl control(5*rhs.size(), 0., 1.e-12, false, false);
- GrowingVectorMemory<> memory;
- SolverCG<> cg(control,memory);
-
- PreconditionSSOR<> prec;
- prec.initialize(mass_matrix, 1.2);
- filtered_precondition.initialize(prec, true);
- // solve
- cg.solve (filtered_mass_matrix, boundary_projection, rhs, filtered_precondition);
- filtered_precondition.apply_constraints(boundary_projection, true);
- filtered_precondition.clear();
- // fill in boundary values
- for (unsigned int i=0; i<dof_to_boundary_mapping.size(); ++i)
- if (dof_to_boundary_mapping[i] != DoFHandler<dim,spacedim>::invalid_dof_index
- && ! excluded_dofs[dof_to_boundary_mapping[i]])
- {
- Assert(numbers::is_finite(boundary_projection(dof_to_boundary_mapping[i])), ExcNumberNotFinite());
+ Vector<double> boundary_projection (rhs.size());
+
+ // Allow for a maximum of 5*n
+ // steps to reduce the residual by
+ // 10^-12. n steps may not be
+ // sufficient, since roundoff
+ // errors may accumulate for badly
+ // conditioned matrices
+ ReductionControl control(5*rhs.size(), 0., 1.e-12, false, false);
+ GrowingVectorMemory<> memory;
+ SolverCG<> cg(control,memory);
+
+ PreconditionSSOR<> prec;
+ prec.initialize(mass_matrix, 1.2);
+ filtered_precondition.initialize(prec, true);
+ // solve
+ cg.solve (filtered_mass_matrix, boundary_projection, rhs, filtered_precondition);
+ filtered_precondition.apply_constraints(boundary_projection, true);
+ filtered_precondition.clear();
+ // fill in boundary values
+ for (unsigned int i=0; i<dof_to_boundary_mapping.size(); ++i)
+ if (dof_to_boundary_mapping[i] != DoFHandler<dim,spacedim>::invalid_dof_index
+ && ! excluded_dofs[dof_to_boundary_mapping[i]])
+ {
+ Assert(numbers::is_finite(boundary_projection(dof_to_boundary_mapping[i])), ExcNumberNotFinite());
- // this dof is on one of the
- // interesting boundary parts
- //
- // remember: i is the global dof
- // number, dof_to_boundary_mapping[i]
- // is the number on the boundary and
- // thus in the solution vector
- boundary_values[i] = boundary_projection(dof_to_boundary_mapping[i]);
- }
-}
+ // this dof is on one of the
+ // interesting boundary parts
+ //
+ // remember: i is the global dof
+ // number, dof_to_boundary_mapping[i]
+ // is the number on the boundary and
+ // thus in the solution vector
+ boundary_values[i] = boundary_projection(dof_to_boundary_mapping[i]);
+ }
+ }
-template <int dim, int spacedim>
-void
-VectorTools::project_boundary_values (const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- std::map<unsigned int,double> &boundary_values,
- std::vector<unsigned int> component_mapping)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- project_boundary_values(StaticMappingQ1<dim,spacedim>::mapping, dof, boundary_functions, q,
- boundary_values, component_mapping);
-}
+ template <int dim, int spacedim>
+ void
+ project_boundary_values (const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ std::map<unsigned int,double> &boundary_values,
+ std::vector<unsigned int> component_mapping)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ project_boundary_values(StaticMappingQ1<dim,spacedim>::mapping, dof, boundary_functions, q,
+ boundary_values, component_mapping);
+ }
-template <int dim, int spacedim>
-void
-VectorTools::project_boundary_values (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- ConstraintMatrix &constraints,
- std::vector<unsigned int> component_mapping)
-{
- std::map<unsigned int,double> boundary_values;
- project_boundary_values (mapping, dof, boundary_functions, q,
- boundary_values, component_mapping);
- std::map<unsigned int,double>::const_iterator boundary_value =
- boundary_values.begin();
- for ( ; boundary_value !=boundary_values.end(); ++boundary_value)
- {
- if (!constraints.is_constrained(boundary_value->first))
- {
- constraints.add_line (boundary_value->first);
- constraints.set_inhomogeneity (boundary_value->first,
- boundary_value->second);
- }
- }
-}
+ template <int dim, int spacedim>
+ void
+ project_boundary_values (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ ConstraintMatrix &constraints,
+ std::vector<unsigned int> component_mapping)
+ {
+ std::map<unsigned int,double> boundary_values;
+ project_boundary_values (mapping, dof, boundary_functions, q,
+ boundary_values, component_mapping);
+ std::map<unsigned int,double>::const_iterator boundary_value =
+ boundary_values.begin();
+ for ( ; boundary_value !=boundary_values.end(); ++boundary_value)
+ {
+ if (!constraints.is_constrained(boundary_value->first))
+ {
+ constraints.add_line (boundary_value->first);
+ constraints.set_inhomogeneity (boundary_value->first,
+ boundary_value->second);
+ }
+ }
+ }
-template <int dim, int spacedim>
-void
-VectorTools::project_boundary_values (const DoFHandler<dim,spacedim> &dof,
- const typename FunctionMap<spacedim>::type &boundary_functions,
- const Quadrature<dim-1> &q,
- ConstraintMatrix &constraints,
- std::vector<unsigned int> component_mapping)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- project_boundary_values(StaticMappingQ1<dim,spacedim>::mapping, dof, boundary_functions, q,
- constraints, component_mapping);
-}
+ template <int dim, int spacedim>
+ void
+ project_boundary_values (const DoFHandler<dim,spacedim> &dof,
+ const typename FunctionMap<spacedim>::type &boundary_functions,
+ const Quadrature<dim-1> &q,
+ ConstraintMatrix &constraints,
+ std::vector<unsigned int> component_mapping)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ project_boundary_values(StaticMappingQ1<dim,spacedim>::mapping, dof, boundary_functions, q,
+ constraints, component_mapping);
+ }
-namespace internal
-{
- namespace VectorTools
+ namespace internal
{
/**
* A structure that stores the dim DoF
}
}
}
-}
-
-namespace internals {
- namespace VectorTools {
- // This function computes the
- // projection of the boundary
- // function on edges for 3D.
+ namespace internals
+ {
+ // This function computes the
+ // projection of the boundary
+ // function on edges for 3D.
template<typename cell_iterator>
void
compute_edge_projection (const cell_iterator& cell,
- const unsigned int face,
- const unsigned int line,
- hp::FEValues<3>& hp_fe_values,
- const Function<3>& boundary_function,
- const unsigned int first_vector_component,
- std::vector<double>& dof_values)
+ const unsigned int face,
+ const unsigned int line,
+ hp::FEValues<3>& hp_fe_values,
+ const Function<3>& boundary_function,
+ const unsigned int first_vector_component,
+ std::vector<double>& dof_values)
{
const double tol = 0.5 * cell->get_fe ().degree * 1e-13 / cell->face (face)->line (line)->diameter ();
const unsigned int dim = 3;
hp_fe_values.reinit
- (cell,
- (cell->active_fe_index () * GeometryInfo<dim>::faces_per_cell + face)
- * GeometryInfo<dim>::lines_per_face + line);
+ (cell,
+ (cell->active_fe_index () * GeometryInfo<dim>::faces_per_cell + face)
+ * GeometryInfo<dim>::lines_per_face + line);
- // Initialize the required
- // objects.
+ // Initialize the required
+ // objects.
const FEValues<dim>&
- fe_values = hp_fe_values.get_present_fe_values ();
+ fe_values = hp_fe_values.get_present_fe_values ();
const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_jacobians ();
+ jacobians = fe_values.get_jacobians ();
const std::vector<Point<dim> >&
- quadrature_points = fe_values.get_quadrature_points ();
+ quadrature_points = fe_values.get_quadrature_points ();
std::vector<Point<dim> > tangentials (fe_values.n_quadrature_points);
std::vector<Vector<double> > values (fe_values.n_quadrature_points,
- Vector<double> (dim));
+ Vector<double> (dim));
- // Get boundary function values
- // at quadrature points.
+ // Get boundary function values
+ // at quadrature points.
boundary_function.vector_value_list (quadrature_points, values);
const std::vector<Point<dim> >&
- reference_quadrature_points = fe_values.get_quadrature ().get_points ();
+ reference_quadrature_points = fe_values.get_quadrature ().get_points ();
const unsigned int superdegree = cell->get_fe ().degree;
const unsigned int degree = superdegree - 1;
- // coordinate directions of
- // the edges of the face.
+ // coordinate directions of
+ // the edges of the face.
const unsigned int
- edge_coordinate_direction
- [GeometryInfo<dim>::faces_per_cell]
- [GeometryInfo<dim>::lines_per_face]
- = { { 2, 2, 1, 1 },
- { 2, 2, 1, 1 },
- { 0, 0, 2, 2 },
- { 0, 0, 2, 2 },
- { 1, 1, 0, 0 },
- { 1, 1, 0, 0 } };
-
- // The interpolation for the
- // lowest order edge shape
- // functions is just the mean
- // value of the tangential
- // components of the boundary
- // function on the edge.
+ edge_coordinate_direction
+ [GeometryInfo<dim>::faces_per_cell]
+ [GeometryInfo<dim>::lines_per_face]
+ = { { 2, 2, 1, 1 },
+ { 2, 2, 1, 1 },
+ { 0, 0, 2, 2 },
+ { 0, 0, 2, 2 },
+ { 1, 1, 0, 0 },
+ { 1, 1, 0, 0 } };
+
+ // The interpolation for the
+ // lowest order edge shape
+ // functions is just the mean
+ // value of the tangential
+ // components of the boundary
+ // function on the edge.
for (unsigned int q_point = 0; q_point < fe_values.n_quadrature_points;
- ++q_point)
- {
- // Therefore compute the
- // tangential of the edge at
- // the quadrature point.
- Point<dim> shifted_reference_point_1 = reference_quadrature_points[q_point];
- Point<dim> shifted_reference_point_2 = reference_quadrature_points[q_point];
-
- shifted_reference_point_1 (edge_coordinate_direction[face][line]) += tol;
- shifted_reference_point_2 (edge_coordinate_direction[face][line]) -= tol;
- tangentials[q_point]
- = (0.5 *
- (fe_values.get_mapping ()
- .transform_unit_to_real_cell (cell,
- shifted_reference_point_1)
- -
- fe_values.get_mapping ()
- .transform_unit_to_real_cell (cell,
- shifted_reference_point_2))
- / tol);
- tangentials[q_point]
- /= std::sqrt (tangentials[q_point].square ());
-
- // Compute the mean value.
- dof_values[line * superdegree]
- += (fe_values.JxW (q_point)
- * (values[q_point] (0) * tangentials[q_point] (0)
- + values[q_point] (1) * tangentials[q_point] (1)
- + values[q_point] (2) * tangentials[q_point] (2))
- / (jacobians[q_point][0][edge_coordinate_direction[face][line]]
- * jacobians[q_point][0][edge_coordinate_direction[face][line]]
- + jacobians[q_point][1][edge_coordinate_direction[face][line]]
- * jacobians[q_point][1][edge_coordinate_direction[face][line]]
- + jacobians[q_point][2][edge_coordinate_direction[face][line]]
- * jacobians[q_point][2][edge_coordinate_direction[face][line]]));
- }
-
- // If there are also higher
- // order shape functions we
- // have still some work left.
+ ++q_point)
+ {
+ // Therefore compute the
+ // tangential of the edge at
+ // the quadrature point.
+ Point<dim> shifted_reference_point_1 = reference_quadrature_points[q_point];
+ Point<dim> shifted_reference_point_2 = reference_quadrature_points[q_point];
+
+ shifted_reference_point_1 (edge_coordinate_direction[face][line]) += tol;
+ shifted_reference_point_2 (edge_coordinate_direction[face][line]) -= tol;
+ tangentials[q_point]
+ = (0.5 *
+ (fe_values.get_mapping ()
+ .transform_unit_to_real_cell (cell,
+ shifted_reference_point_1)
+ -
+ fe_values.get_mapping ()
+ .transform_unit_to_real_cell (cell,
+ shifted_reference_point_2))
+ / tol);
+ tangentials[q_point]
+ /= std::sqrt (tangentials[q_point].square ());
+
+ // Compute the mean value.
+ dof_values[line * superdegree]
+ += (fe_values.JxW (q_point)
+ * (values[q_point] (0) * tangentials[q_point] (0)
+ + values[q_point] (1) * tangentials[q_point] (1)
+ + values[q_point] (2) * tangentials[q_point] (2))
+ / (jacobians[q_point][0][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][0][edge_coordinate_direction[face][line]]
+ + jacobians[q_point][1][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][1][edge_coordinate_direction[face][line]]
+ + jacobians[q_point][2][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][2][edge_coordinate_direction[face][line]]));
+ }
+
+ // If there are also higher
+ // order shape functions we
+ // have still some work left.
if (degree > 0)
- {
- const FEValuesExtractors::Vector vec (first_vector_component);
- FullMatrix<double> assembling_matrix (degree, fe_values.n_quadrature_points);
- Vector<double> assembling_vector (fe_values.n_quadrature_points);
-
- // We set up a linear system
- // of equations to get the
- // values for the remaining
- // degrees of freedom
- // associated with the edge.
- for (unsigned int q_point = 0; q_point < fe_values.n_quadrature_points;
- ++q_point)
- {
- // The right hand side of
- // the corresponding
- // problem is the
- // tangential components of
- // the residual of the
- // boundary function and
- // the interpolated part
- // above.
- const Tensor<1, dim> tmp
- =
- std::sqrt (fe_values.JxW (q_point)
- / (jacobians[q_point][0][edge_coordinate_direction[face][line]]
- * jacobians[q_point][0][edge_coordinate_direction[face][line]]
- +
- jacobians[q_point][1][edge_coordinate_direction[face][line]]
- * jacobians[q_point][1][edge_coordinate_direction[face][line]]
- +
- jacobians[q_point][2][edge_coordinate_direction[face][line]]
- * jacobians[q_point][2][edge_coordinate_direction[face][line]]))
- * tangentials[q_point];
-
- const Tensor<1, dim> shape_value
- = fe_values[vec].value (cell->get_fe ()
- .face_to_cell_index (line * superdegree, face),
- q_point);
- // In the weak form the
- // right hand side function
- // is multiplicated by the
- // higher order shape
- // functions.
- assembling_vector (q_point)
- = ((values[q_point] (0)
- -
- dof_values[line * superdegree] * shape_value[0]) * tmp[0]
- +
- (values[q_point] (1)
- -
- dof_values[line * superdegree] * shape_value[1]) * tmp[1]
- +
- (values[q_point] (2)
- -
- dof_values[line * superdegree] * shape_value[2]) * tmp[2]);
-
- for (unsigned int i = 0; i < degree; ++i)
- assembling_matrix (i, q_point)
- = fe_values[vec].value (cell->get_fe ()
- .face_to_cell_index (i + line * superdegree + 1,
- face),
- q_point) * tmp;
- }
-
- FullMatrix<double> cell_matrix (degree, degree);
-
- // Create the system matrix
- // by multiplying the
- // assembling matrix with its
- // transposed.
- assembling_matrix.mTmult (cell_matrix, assembling_matrix);
-
- FullMatrix<double> cell_matrix_inv (degree, degree);
- // Compute its inverse.
- cell_matrix_inv.invert (cell_matrix);
-
- Vector<double> cell_rhs (degree);
-
- // Create the system right
- // hand side vector by
- // multiplying the assembling
- // matrix with the assembling
- // vector.
- assembling_matrix.vmult (cell_rhs, assembling_vector);
-
- Vector<double> solution (degree);
-
- cell_matrix_inv.vmult (solution, cell_rhs);
- // Store the computed values.
- for (unsigned int i = 0; i < degree; ++i)
- dof_values[i + line * superdegree + 1] = solution (i);
- }
+ {
+ const FEValuesExtractors::Vector vec (first_vector_component);
+ FullMatrix<double> assembling_matrix (degree, fe_values.n_quadrature_points);
+ Vector<double> assembling_vector (fe_values.n_quadrature_points);
+
+ // We set up a linear system
+ // of equations to get the
+ // values for the remaining
+ // degrees of freedom
+ // associated with the edge.
+ for (unsigned int q_point = 0; q_point < fe_values.n_quadrature_points;
+ ++q_point)
+ {
+ // The right hand side of
+ // the corresponding
+ // problem is the
+ // tangential components of
+ // the residual of the
+ // boundary function and
+ // the interpolated part
+ // above.
+ const Tensor<1, dim> tmp
+ =
+ std::sqrt (fe_values.JxW (q_point)
+ / (jacobians[q_point][0][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][0][edge_coordinate_direction[face][line]]
+ +
+ jacobians[q_point][1][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][1][edge_coordinate_direction[face][line]]
+ +
+ jacobians[q_point][2][edge_coordinate_direction[face][line]]
+ * jacobians[q_point][2][edge_coordinate_direction[face][line]]))
+ * tangentials[q_point];
+
+ const Tensor<1, dim> shape_value
+ = fe_values[vec].value (cell->get_fe ()
+ .face_to_cell_index (line * superdegree, face),
+ q_point);
+ // In the weak form the
+ // right hand side function
+ // is multiplicated by the
+ // higher order shape
+ // functions.
+ assembling_vector (q_point)
+ = ((values[q_point] (0)
+ -
+ dof_values[line * superdegree] * shape_value[0]) * tmp[0]
+ +
+ (values[q_point] (1)
+ -
+ dof_values[line * superdegree] * shape_value[1]) * tmp[1]
+ +
+ (values[q_point] (2)
+ -
+ dof_values[line * superdegree] * shape_value[2]) * tmp[2]);
+
+ for (unsigned int i = 0; i < degree; ++i)
+ assembling_matrix (i, q_point)
+ = fe_values[vec].value (cell->get_fe ()
+ .face_to_cell_index (i + line * superdegree + 1,
+ face),
+ q_point) * tmp;
+ }
+
+ FullMatrix<double> cell_matrix (degree, degree);
+
+ // Create the system matrix
+ // by multiplying the
+ // assembling matrix with its
+ // transposed.
+ assembling_matrix.mTmult (cell_matrix, assembling_matrix);
+
+ FullMatrix<double> cell_matrix_inv (degree, degree);
+ // Compute its inverse.
+ cell_matrix_inv.invert (cell_matrix);
+
+ Vector<double> cell_rhs (degree);
+
+ // Create the system right
+ // hand side vector by
+ // multiplying the assembling
+ // matrix with the assembling
+ // vector.
+ assembling_matrix.vmult (cell_rhs, assembling_vector);
+
+ Vector<double> solution (degree);
+
+ cell_matrix_inv.vmult (solution, cell_rhs);
+ // Store the computed values.
+ for (unsigned int i = 0; i < degree; ++i)
+ dof_values[i + line * superdegree + 1] = solution (i);
+ }
}
- // dummy implementation of above
- // function for all other
- // dimensions
+ // dummy implementation of above
+ // function for all other
+ // dimensions
template<int dim, typename cell_iterator>
void
compute_edge_projection (const cell_iterator&,
- const unsigned int,
- const unsigned int,
- hp::FEValues<dim>&,
- const Function<dim>&,
- const unsigned int,
- std::vector<double>&)
+ const unsigned int,
+ const unsigned int,
+ hp::FEValues<dim>&,
+ const Function<dim>&,
+ const unsigned int,
+ std::vector<double>&)
{
Assert (false, ExcInternalError ());
}
- // This function computes the
- // projection of the boundary
- // function on the interior of
- // faces.
+ // This function computes the
+ // projection of the boundary
+ // function on the interior of
+ // faces.
template<int dim, typename cell_iterator>
void
compute_face_projection_curl_conforming (const cell_iterator& cell,
- const unsigned int face,
- hp::FEValues<dim>& hp_fe_values,
- const Function<dim>& boundary_function,
- const unsigned int first_vector_component,
- std::vector<double>& dof_values)
+ const unsigned int face,
+ hp::FEValues<dim>& hp_fe_values,
+ const Function<dim>& boundary_function,
+ const unsigned int first_vector_component,
+ std::vector<double>& dof_values)
{
hp_fe_values.reinit (cell, cell->active_fe_index ()
- * GeometryInfo<dim>::faces_per_cell + face);
- // Initialize the required
- // objects.
+ * GeometryInfo<dim>::faces_per_cell + face);
+ // Initialize the required
+ // objects.
const FEValues<dim>&
- fe_values = hp_fe_values.get_present_fe_values ();
+ fe_values = hp_fe_values.get_present_fe_values ();
const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_jacobians ();
+ jacobians = fe_values.get_jacobians ();
std::vector<Vector<double> >
- values (fe_values.n_quadrature_points, Vector<double> (dim));
+ values (fe_values.n_quadrature_points, Vector<double> (dim));
switch (dim)
- {
- case 2:
- {
- const std::vector<Point<dim> >&
- quadrature_points = fe_values.get_quadrature_points ();
- std::vector<Point<dim> >
- tangentials (fe_values.n_quadrature_points);
-
- // Get boundary function
- // values at quadrature
- // points.
- boundary_function.vector_value_list (quadrature_points, values);
-
- const std::vector<Point<dim> >&
- reference_quadrature_points = fe_values.get_quadrature ().get_points ();
- const unsigned int degree = cell->get_fe ().degree - 1;
-
- // coordinate directions
- // of the face.
- const unsigned int
- face_coordinate_direction[GeometryInfo<dim>::faces_per_cell]
- = { 1, 1, 0, 0 };
-
- // The interpolation for
- // the lowest order face
- // shape functions is just
- // the mean value of the
- // tangential components
- // of the boundary function
- // on the edge.
- for (unsigned int q_point = 0;
- q_point < fe_values.n_quadrature_points; ++q_point)
- {
- // Therefore compute the
- // tangential of the
- // face at the quadrature
- // point.
- Point<dim> shifted_reference_point_1
- = reference_quadrature_points[q_point];
- Point<dim> shifted_reference_point_2
- = reference_quadrature_points[q_point];
-
- shifted_reference_point_1 (face_coordinate_direction[face])
- += 1e-13;
- shifted_reference_point_2 (face_coordinate_direction[face])
- -= 1e-13;
- tangentials[q_point]
- = 2e13
- * (fe_values.get_mapping ()
- .transform_unit_to_real_cell (cell,
- shifted_reference_point_1)
- -
- fe_values.get_mapping ()
- .transform_unit_to_real_cell (cell,
- shifted_reference_point_2));
- tangentials[q_point]
- /= std::sqrt (tangentials[q_point].square ());
- // Compute the mean
- // value.
- dof_values[0]
- += fe_values.JxW (q_point)
- * (values[q_point] (0)
- * tangentials[q_point] (0)
- + values[q_point] (1) * tangentials[q_point] (1))
- / (jacobians[q_point][0][face_coordinate_direction[face]]
- * jacobians[q_point][0][face_coordinate_direction[face]]
- + jacobians[q_point][1][face_coordinate_direction[face]]
- * jacobians[q_point][1][face_coordinate_direction[face]]);
- }
-
- // If there are also
- // higher order shape
- // functions we have
- // still some work left.
- if (degree > 0)
- {
- const FEValuesExtractors::Vector vec (first_vector_component);
- FullMatrix<double> assembling_matrix (degree,
- fe_values.n_quadrature_points);
- Vector<double> assembling_vector (fe_values.n_quadrature_points);
-
- // We set up a
- // linear system
- // of equations to
- // get the values
- // for the
- // remaining degrees
- // of freedom
- // associated with
- // the face.
- for (unsigned int q_point = 0;
- q_point < fe_values.n_quadrature_points; ++q_point)
- {
- // The right
- // hand side of
- // the corresponding
- // problem is
- // the tangential
- // components of
- // the residual
- // of the boundary
- // function and
- // the interpolated
- // part above.
- const Tensor<1, dim> tmp
- = std::sqrt (fe_values.JxW (q_point)
- / std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
- * jacobians[q_point][0][face_coordinate_direction[face]]
- + jacobians[q_point][1][face_coordinate_direction[face]]
- * jacobians[q_point][1][face_coordinate_direction[face]]))
- * tangentials[q_point];
-
- const Tensor<1, dim> shape_value
- = fe_values[vec].value (cell->get_fe ()
- .face_to_cell_index (0, face),
- q_point);
-
- assembling_vector (q_point) = (values[q_point] (0)
- -
- dof_values[0] * shape_value[0]) * tmp[0]
- +
- (values[q_point] (1)
- -
- dof_values[1] * shape_value[1]) * tmp[1];
-
- // In the weak
- // form the
- // right hand
- // side function
- // is multiplicated
- // by the higher
- // order shape
- // functions.
- for (unsigned int i = 0; i < degree; ++i)
- assembling_matrix (i, q_point)
- = fe_values[vec].value (cell->get_fe ()
- .face_to_cell_index (i + 1, face),
- q_point) * tmp;
- }
-
- FullMatrix<double> cell_matrix (degree, degree);
-
- // Create the system
- // matrix by multiplying
- // the assembling
- // matrix with its
- // transposed.
- assembling_matrix.mTmult (cell_matrix, assembling_matrix);
-
- FullMatrix<double> cell_matrix_inv (degree, degree);
- // Compute its inverse.
- cell_matrix_inv.invert (cell_matrix);
-
- Vector<double> cell_rhs (degree);
-
- // Create the system
- // right hand side
- // vector by
- // multiplying the
- // assembling matrix
- // with the assembling
- // vector.
- assembling_matrix.vmult (cell_rhs, assembling_vector);
-
- Vector<double> solution (degree);
-
- cell_matrix_inv.vmult (solution, cell_rhs);
-
- // Store the computed
- // values.
- for (unsigned int i = 0; i < degree; ++i)
- dof_values[i + 1] = solution (i);
- }
-
- break;
- }
-
- case 3:
- {
- const std::vector<Point<dim> >&
- quadrature_points = fe_values.get_quadrature_points ();
-
- // Get boundary function
- // values at quadrature
- // points.
- boundary_function.vector_value_list (quadrature_points, values);
-
- const FEValuesExtractors::Vector vec (first_vector_component);
- const unsigned int superdegree = cell->get_fe ().degree;
- const unsigned int degree = superdegree - 1;
- FullMatrix<double>
- assembling_matrix (degree * superdegree,
- dim * fe_values.n_quadrature_points);
- Vector<double> assembling_vector (assembling_matrix.n ());
- Vector<double> cell_rhs (assembling_matrix.m ());
- FullMatrix<double> cell_matrix (assembling_matrix.m (),
- assembling_matrix.m ());
- FullMatrix<double> cell_matrix_inv (assembling_matrix.m (),
- assembling_matrix.m ());
- Vector<double> solution (cell_matrix.m ());
-
- // Get coordinate directions
- // of the face.
- const unsigned int
- global_face_coordinate_directions[GeometryInfo<3>::faces_per_cell][2]
- = { { 1, 2 },
- { 1, 2 },
- { 2, 0 },
- { 2, 0 },
- { 0, 1 },
- { 0, 1 } };
-
- // The projection is
- // divided into two steps.
- // In the first step we
- // project the boundary
- // function on the
- // horizontal shape
- // functions. Then the
- // bounary function is
- // projected on the
- // vertical shape
- // functions. We begin
- // with the horizontal
- // shape functions and
- // set up a linear system
- // of equations to get
- // the values for degrees
- // of freedom associated
- // with the interior of
- // the face.
- for (unsigned int q_point = 0;
- q_point < fe_values.n_quadrature_points; ++q_point)
- {
- // The right hand
- // side of the
- // corresponding problem
- // is the residual
- // of the boundary
- // function and
- // the already
- // interpolated part
- // on the edges.
- Tensor<1, dim> tmp;
-
- for (unsigned int d = 0; d < dim; ++d)
- tmp[d] = values[q_point] (d);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j <= degree; ++j)
- tmp -= dof_values[(i + 2) * superdegree + j]
- * fe_values[vec].value (cell->get_fe ().face_to_cell_index
- ((i + 2) * superdegree + j,
- face), q_point);
-
- const double JxW
- = std::sqrt (fe_values.JxW (q_point)
- / ((jacobians[q_point][0][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][0][global_face_coordinate_directions[face][0]]
- +
- jacobians[q_point][1][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][1][global_face_coordinate_directions[face][0]]
- +
- jacobians[q_point][2][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][2][global_face_coordinate_directions[face][0]])
- *
- (jacobians[q_point][0][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][0][global_face_coordinate_directions[face][1]]
- +
- jacobians[q_point][1][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][1][global_face_coordinate_directions[face][1]]
- +
- jacobians[q_point][2][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][2][global_face_coordinate_directions[face][1]])));
-
- // In the weak form
- // the right hand
- // side function
- // is multiplicated
- // by the horizontal
- // shape functions
- // defined in the
- // interior of
- // the face.
- for (unsigned int d = 0; d < dim; ++d)
- assembling_vector (dim * q_point + d) = JxW * tmp[d];
-
- for (unsigned int i = 0; i <= degree; ++i)
- for (unsigned int j = 0; j < degree; ++j)
- {
- const Tensor<1, dim> shape_value
- = (JxW
- * fe_values[vec].value (cell->get_fe ()
- .face_to_cell_index
- ((i + GeometryInfo<dim>::lines_per_face)
- * degree
- + j
- + GeometryInfo<dim>::lines_per_face,
- face),
- q_point));
-
- for (unsigned int d = 0; d < dim; ++d)
- assembling_matrix (i * degree + j,
- dim * q_point + d)
- = shape_value[d];
- }
- }
-
- // Create the system
- // matrix by
- // multiplying the
- // assembling matrix
- // with its transposed
- // and the right
- // hand side vector
- // by mutliplying
- // the assembling
- // matrix with the
- // assembling vector.
- // Invert the system
- // matrix.
- assembling_matrix.mTmult (cell_matrix, assembling_matrix);
- cell_matrix_inv.invert (cell_matrix);
- assembling_matrix.vmult (cell_rhs, assembling_vector);
- cell_matrix_inv.vmult (solution, cell_rhs);
-
- // Store the computed
- // values.
- for (unsigned int i = 0; i <= degree; ++i)
- for (unsigned int j = 0; j < degree; ++j)
- dof_values[(i + GeometryInfo<dim>::lines_per_face)
- * degree + j + GeometryInfo<dim>::lines_per_face]
- = solution (i * degree + j);
-
- // Now we do the
- // same as above
- // with the vertical
- // shape functions
- // instead of the
- // horizontal ones.
- for (unsigned int q_point = 0;
- q_point < fe_values.n_quadrature_points; ++q_point)
- {
- Tensor<1, dim> tmp;
-
- for (unsigned int d = 0; d < dim; ++d)
- tmp[d] = values[q_point] (d);
-
- for (unsigned int i = 0; i < 2; ++i)
- for (unsigned int j = 0; j <= degree; ++j)
- tmp
- -= dof_values[i * superdegree + j]
- * fe_values[vec].value (cell->get_fe ().face_to_cell_index
- (i * superdegree + j, face), q_point);
-
- const double JxW
- = std::sqrt (fe_values.JxW (q_point)
- / ((jacobians[q_point][0][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][0][global_face_coordinate_directions[face][0]]
- +
- jacobians[q_point][1][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][1][global_face_coordinate_directions[face][0]]
- +
- jacobians[q_point][2][global_face_coordinate_directions[face][0]]
- * jacobians[q_point][2][global_face_coordinate_directions[face][0]])
- *
- (jacobians[q_point][0][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][0][global_face_coordinate_directions[face][1]]
- +
- jacobians[q_point][1][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][1][global_face_coordinate_directions[face][1]]
- +
- jacobians[q_point][2][global_face_coordinate_directions[face][1]]
- * jacobians[q_point][2][global_face_coordinate_directions[face][1]])));
-
- for (unsigned int d = 0; d < dim; ++d)
- assembling_vector (dim * q_point + d) = JxW * tmp[d];
-
- for (unsigned int i = 0; i < degree; ++i)
- for (unsigned int j = 0; j <= degree; ++j)
- {
- const Tensor<1, dim> shape_value
- = (JxW
- * fe_values[vec].value (cell->get_fe ().face_to_cell_index
- ((i + degree + GeometryInfo<dim>::lines_per_face)
- * superdegree + j, face), q_point));
-
- for (unsigned int d = 0; d < dim; ++d)
- assembling_matrix (i * superdegree + j, dim * q_point + d)
- = shape_value[d];
- }
- }
-
- assembling_matrix.mTmult (cell_matrix, assembling_matrix);
- cell_matrix_inv.invert (cell_matrix);
- assembling_matrix.vmult (cell_rhs, assembling_vector);
- cell_matrix_inv.vmult (solution, cell_rhs);
-
- for (unsigned int i = 0; i < degree; ++i)
- for (unsigned int j = 0; j <= degree; ++j)
- dof_values[(i + degree + GeometryInfo<dim>::lines_per_face) * superdegree + j]
- = solution (i * superdegree + j);
-
- break;
- }
-
- default:
- Assert (false, ExcNotImplemented ());
- }
+ {
+ case 2:
+ {
+ const std::vector<Point<dim> >&
+ quadrature_points = fe_values.get_quadrature_points ();
+ std::vector<Point<dim> >
+ tangentials (fe_values.n_quadrature_points);
+
+ // Get boundary function
+ // values at quadrature
+ // points.
+ boundary_function.vector_value_list (quadrature_points, values);
+
+ const std::vector<Point<dim> >&
+ reference_quadrature_points = fe_values.get_quadrature ().get_points ();
+ const unsigned int degree = cell->get_fe ().degree - 1;
+
+ // coordinate directions
+ // of the face.
+ const unsigned int
+ face_coordinate_direction[GeometryInfo<dim>::faces_per_cell]
+ = { 1, 1, 0, 0 };
+
+ // The interpolation for
+ // the lowest order face
+ // shape functions is just
+ // the mean value of the
+ // tangential components
+ // of the boundary function
+ // on the edge.
+ for (unsigned int q_point = 0;
+ q_point < fe_values.n_quadrature_points; ++q_point)
+ {
+ // Therefore compute the
+ // tangential of the
+ // face at the quadrature
+ // point.
+ Point<dim> shifted_reference_point_1
+ = reference_quadrature_points[q_point];
+ Point<dim> shifted_reference_point_2
+ = reference_quadrature_points[q_point];
+
+ shifted_reference_point_1 (face_coordinate_direction[face])
+ += 1e-13;
+ shifted_reference_point_2 (face_coordinate_direction[face])
+ -= 1e-13;
+ tangentials[q_point]
+ = 2e13
+ * (fe_values.get_mapping ()
+ .transform_unit_to_real_cell (cell,
+ shifted_reference_point_1)
+ -
+ fe_values.get_mapping ()
+ .transform_unit_to_real_cell (cell,
+ shifted_reference_point_2));
+ tangentials[q_point]
+ /= std::sqrt (tangentials[q_point].square ());
+ // Compute the mean
+ // value.
+ dof_values[0]
+ += fe_values.JxW (q_point)
+ * (values[q_point] (0)
+ * tangentials[q_point] (0)
+ + values[q_point] (1) * tangentials[q_point] (1))
+ / (jacobians[q_point][0][face_coordinate_direction[face]]
+ * jacobians[q_point][0][face_coordinate_direction[face]]
+ + jacobians[q_point][1][face_coordinate_direction[face]]
+ * jacobians[q_point][1][face_coordinate_direction[face]]);
+ }
+
+ // If there are also
+ // higher order shape
+ // functions we have
+ // still some work left.
+ if (degree > 0)
+ {
+ const FEValuesExtractors::Vector vec (first_vector_component);
+ FullMatrix<double> assembling_matrix (degree,
+ fe_values.n_quadrature_points);
+ Vector<double> assembling_vector (fe_values.n_quadrature_points);
+
+ // We set up a
+ // linear system
+ // of equations to
+ // get the values
+ // for the
+ // remaining degrees
+ // of freedom
+ // associated with
+ // the face.
+ for (unsigned int q_point = 0;
+ q_point < fe_values.n_quadrature_points; ++q_point)
+ {
+ // The right
+ // hand side of
+ // the corresponding
+ // problem is
+ // the tangential
+ // components of
+ // the residual
+ // of the boundary
+ // function and
+ // the interpolated
+ // part above.
+ const Tensor<1, dim> tmp
+ = std::sqrt (fe_values.JxW (q_point)
+ / std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
+ * jacobians[q_point][0][face_coordinate_direction[face]]
+ + jacobians[q_point][1][face_coordinate_direction[face]]
+ * jacobians[q_point][1][face_coordinate_direction[face]]))
+ * tangentials[q_point];
+
+ const Tensor<1, dim> shape_value
+ = fe_values[vec].value (cell->get_fe ()
+ .face_to_cell_index (0, face),
+ q_point);
+
+ assembling_vector (q_point) = (values[q_point] (0)
+ -
+ dof_values[0] * shape_value[0]) * tmp[0]
+ +
+ (values[q_point] (1)
+ -
+ dof_values[1] * shape_value[1]) * tmp[1];
+
+ // In the weak
+ // form the
+ // right hand
+ // side function
+ // is multiplicated
+ // by the higher
+ // order shape
+ // functions.
+ for (unsigned int i = 0; i < degree; ++i)
+ assembling_matrix (i, q_point)
+ = fe_values[vec].value (cell->get_fe ()
+ .face_to_cell_index (i + 1, face),
+ q_point) * tmp;
+ }
+
+ FullMatrix<double> cell_matrix (degree, degree);
+
+ // Create the system
+ // matrix by multiplying
+ // the assembling
+ // matrix with its
+ // transposed.
+ assembling_matrix.mTmult (cell_matrix, assembling_matrix);
+
+ FullMatrix<double> cell_matrix_inv (degree, degree);
+ // Compute its inverse.
+ cell_matrix_inv.invert (cell_matrix);
+
+ Vector<double> cell_rhs (degree);
+
+ // Create the system
+ // right hand side
+ // vector by
+ // multiplying the
+ // assembling matrix
+ // with the assembling
+ // vector.
+ assembling_matrix.vmult (cell_rhs, assembling_vector);
+
+ Vector<double> solution (degree);
+
+ cell_matrix_inv.vmult (solution, cell_rhs);
+
+ // Store the computed
+ // values.
+ for (unsigned int i = 0; i < degree; ++i)
+ dof_values[i + 1] = solution (i);
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ const std::vector<Point<dim> >&
+ quadrature_points = fe_values.get_quadrature_points ();
+
+ // Get boundary function
+ // values at quadrature
+ // points.
+ boundary_function.vector_value_list (quadrature_points, values);
+
+ const FEValuesExtractors::Vector vec (first_vector_component);
+ const unsigned int superdegree = cell->get_fe ().degree;
+ const unsigned int degree = superdegree - 1;
+ FullMatrix<double>
+ assembling_matrix (degree * superdegree,
+ dim * fe_values.n_quadrature_points);
+ Vector<double> assembling_vector (assembling_matrix.n ());
+ Vector<double> cell_rhs (assembling_matrix.m ());
+ FullMatrix<double> cell_matrix (assembling_matrix.m (),
+ assembling_matrix.m ());
+ FullMatrix<double> cell_matrix_inv (assembling_matrix.m (),
+ assembling_matrix.m ());
+ Vector<double> solution (cell_matrix.m ());
+
+ // Get coordinate directions
+ // of the face.
+ const unsigned int
+ global_face_coordinate_directions[GeometryInfo<3>::faces_per_cell][2]
+ = { { 1, 2 },
+ { 1, 2 },
+ { 2, 0 },
+ { 2, 0 },
+ { 0, 1 },
+ { 0, 1 } };
+
+ // The projection is
+ // divided into two steps.
+ // In the first step we
+ // project the boundary
+ // function on the
+ // horizontal shape
+ // functions. Then the
+ // bounary function is
+ // projected on the
+ // vertical shape
+ // functions. We begin
+ // with the horizontal
+ // shape functions and
+ // set up a linear system
+ // of equations to get
+ // the values for degrees
+ // of freedom associated
+ // with the interior of
+ // the face.
+ for (unsigned int q_point = 0;
+ q_point < fe_values.n_quadrature_points; ++q_point)
+ {
+ // The right hand
+ // side of the
+ // corresponding problem
+ // is the residual
+ // of the boundary
+ // function and
+ // the already
+ // interpolated part
+ // on the edges.
+ Tensor<1, dim> tmp;
+
+ for (unsigned int d = 0; d < dim; ++d)
+ tmp[d] = values[q_point] (d);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= degree; ++j)
+ tmp -= dof_values[(i + 2) * superdegree + j]
+ * fe_values[vec].value (cell->get_fe ().face_to_cell_index
+ ((i + 2) * superdegree + j,
+ face), q_point);
+
+ const double JxW
+ = std::sqrt (fe_values.JxW (q_point)
+ / ((jacobians[q_point][0][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][0][global_face_coordinate_directions[face][0]]
+ +
+ jacobians[q_point][1][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][1][global_face_coordinate_directions[face][0]]
+ +
+ jacobians[q_point][2][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][2][global_face_coordinate_directions[face][0]])
+ *
+ (jacobians[q_point][0][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][0][global_face_coordinate_directions[face][1]]
+ +
+ jacobians[q_point][1][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][1][global_face_coordinate_directions[face][1]]
+ +
+ jacobians[q_point][2][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][2][global_face_coordinate_directions[face][1]])));
+
+ // In the weak form
+ // the right hand
+ // side function
+ // is multiplicated
+ // by the horizontal
+ // shape functions
+ // defined in the
+ // interior of
+ // the face.
+ for (unsigned int d = 0; d < dim; ++d)
+ assembling_vector (dim * q_point + d) = JxW * tmp[d];
+
+ for (unsigned int i = 0; i <= degree; ++i)
+ for (unsigned int j = 0; j < degree; ++j)
+ {
+ const Tensor<1, dim> shape_value
+ = (JxW
+ * fe_values[vec].value (cell->get_fe ()
+ .face_to_cell_index
+ ((i + GeometryInfo<dim>::lines_per_face)
+ * degree
+ + j
+ + GeometryInfo<dim>::lines_per_face,
+ face),
+ q_point));
+
+ for (unsigned int d = 0; d < dim; ++d)
+ assembling_matrix (i * degree + j,
+ dim * q_point + d)
+ = shape_value[d];
+ }
+ }
+
+ // Create the system
+ // matrix by
+ // multiplying the
+ // assembling matrix
+ // with its transposed
+ // and the right
+ // hand side vector
+ // by mutliplying
+ // the assembling
+ // matrix with the
+ // assembling vector.
+ // Invert the system
+ // matrix.
+ assembling_matrix.mTmult (cell_matrix, assembling_matrix);
+ cell_matrix_inv.invert (cell_matrix);
+ assembling_matrix.vmult (cell_rhs, assembling_vector);
+ cell_matrix_inv.vmult (solution, cell_rhs);
+
+ // Store the computed
+ // values.
+ for (unsigned int i = 0; i <= degree; ++i)
+ for (unsigned int j = 0; j < degree; ++j)
+ dof_values[(i + GeometryInfo<dim>::lines_per_face)
+ * degree + j + GeometryInfo<dim>::lines_per_face]
+ = solution (i * degree + j);
+
+ // Now we do the
+ // same as above
+ // with the vertical
+ // shape functions
+ // instead of the
+ // horizontal ones.
+ for (unsigned int q_point = 0;
+ q_point < fe_values.n_quadrature_points; ++q_point)
+ {
+ Tensor<1, dim> tmp;
+
+ for (unsigned int d = 0; d < dim; ++d)
+ tmp[d] = values[q_point] (d);
+
+ for (unsigned int i = 0; i < 2; ++i)
+ for (unsigned int j = 0; j <= degree; ++j)
+ tmp
+ -= dof_values[i * superdegree + j]
+ * fe_values[vec].value (cell->get_fe ().face_to_cell_index
+ (i * superdegree + j, face), q_point);
+
+ const double JxW
+ = std::sqrt (fe_values.JxW (q_point)
+ / ((jacobians[q_point][0][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][0][global_face_coordinate_directions[face][0]]
+ +
+ jacobians[q_point][1][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][1][global_face_coordinate_directions[face][0]]
+ +
+ jacobians[q_point][2][global_face_coordinate_directions[face][0]]
+ * jacobians[q_point][2][global_face_coordinate_directions[face][0]])
+ *
+ (jacobians[q_point][0][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][0][global_face_coordinate_directions[face][1]]
+ +
+ jacobians[q_point][1][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][1][global_face_coordinate_directions[face][1]]
+ +
+ jacobians[q_point][2][global_face_coordinate_directions[face][1]]
+ * jacobians[q_point][2][global_face_coordinate_directions[face][1]])));
+
+ for (unsigned int d = 0; d < dim; ++d)
+ assembling_vector (dim * q_point + d) = JxW * tmp[d];
+
+ for (unsigned int i = 0; i < degree; ++i)
+ for (unsigned int j = 0; j <= degree; ++j)
+ {
+ const Tensor<1, dim> shape_value
+ = (JxW
+ * fe_values[vec].value (cell->get_fe ().face_to_cell_index
+ ((i + degree + GeometryInfo<dim>::lines_per_face)
+ * superdegree + j, face), q_point));
+
+ for (unsigned int d = 0; d < dim; ++d)
+ assembling_matrix (i * superdegree + j, dim * q_point + d)
+ = shape_value[d];
+ }
+ }
+
+ assembling_matrix.mTmult (cell_matrix, assembling_matrix);
+ cell_matrix_inv.invert (cell_matrix);
+ assembling_matrix.vmult (cell_rhs, assembling_vector);
+ cell_matrix_inv.vmult (solution, cell_rhs);
+
+ for (unsigned int i = 0; i < degree; ++i)
+ for (unsigned int j = 0; j <= degree; ++j)
+ dof_values[(i + degree + GeometryInfo<dim>::lines_per_face) * superdegree + j]
+ = solution (i * superdegree + j);
+
+ break;
+ }
+
+ default:
+ Assert (false, ExcNotImplemented ());
+ }
}
}
-}
-template <int dim>
-void
-VectorTools::
-project_boundary_values_curl_conforming (const DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const Mapping<dim>& mapping)
-{
- // Projection-based interpolation
- // is performed in two (in 2D)
- // respectively three (in 3D)
- // steps. First the tangential
- // component of the function is
- // interpolated on each edge. This
- // gives the values for the degrees
- // of freedom corresponding to the
- // lowest order edge shape
- // functions. Then the interpolated
- // part of the function is
- // subtracted and we project the
- // tangential component of the
- // residual onto the space of the
- // remaining (higher order) edge
- // shape functions. This is done by
- // building a linear system of
- // equations of dimension
- // <tt>degree</tt>. The solution
- // gives us the values for the
- // degrees of freedom corresponding
- // to the remaining edge shape
- // functions. Now we are done for
- // 2D, but in 3D we possibly have
- // also degrees of freedom, which
- // are located in the interior of
- // the faces. Therefore we compute
- // the residual of the function
- // describing the boundary values
- // and the interpolated part, which
- // we have computed in the last two
- // steps. On the faces there are
- // two kinds of shape functions,
- // the horizontal and the vertical
- // ones. Thus we have to solve two
- // linear systems of equations of
- // size <tt>degree * (degree +
- // 1)<tt> to obtain the values for
- // the corresponding degrees of
- // freedom.
- const unsigned int superdegree = dof_handler.get_fe ().degree;
- const QGauss<dim - 1> reference_face_quadrature (2 * superdegree);
- const unsigned int dofs_per_face = dof_handler.get_fe ().dofs_per_face;
- hp::FECollection<dim> fe_collection (dof_handler.get_fe ());
- hp::MappingCollection<dim> mapping_collection (mapping);
- hp::QCollection<dim> face_quadrature_collection;
-
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- face_quadrature_collection.push_back
- (QProjector<dim>::project_to_face (reference_face_quadrature, face));
-
- hp::FEValues<dim> fe_face_values (mapping_collection, fe_collection,
- face_quadrature_collection,
- update_jacobians |
- update_JxW_values |
- update_quadrature_points |
- update_values);
-
- std::vector<double> dof_values (dofs_per_face);
- std::vector<unsigned int> face_dof_indices (dofs_per_face);
- typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
-
- switch (dim)
- {
- case 2:
+ template <int dim>
+ void
+
+ project_boundary_values_curl_conforming (const DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const Mapping<dim>& mapping)
+ {
+ // Projection-based interpolation
+ // is performed in two (in 2D)
+ // respectively three (in 3D)
+ // steps. First the tangential
+ // component of the function is
+ // interpolated on each edge. This
+ // gives the values for the degrees
+ // of freedom corresponding to the
+ // lowest order edge shape
+ // functions. Then the interpolated
+ // part of the function is
+ // subtracted and we project the
+ // tangential component of the
+ // residual onto the space of the
+ // remaining (higher order) edge
+ // shape functions. This is done by
+ // building a linear system of
+ // equations of dimension
+ // <tt>degree</tt>. The solution
+ // gives us the values for the
+ // degrees of freedom corresponding
+ // to the remaining edge shape
+ // functions. Now we are done for
+ // 2D, but in 3D we possibly have
+ // also degrees of freedom, which
+ // are located in the interior of
+ // the faces. Therefore we compute
+ // the residual of the function
+ // describing the boundary values
+ // and the interpolated part, which
+ // we have computed in the last two
+ // steps. On the faces there are
+ // two kinds of shape functions,
+ // the horizontal and the vertical
+ // ones. Thus we have to solve two
+ // linear systems of equations of
+ // size <tt>degree * (degree +
+ // 1)<tt> to obtain the values for
+ // the corresponding degrees of
+ // freedom.
+ const unsigned int superdegree = dof_handler.get_fe ().degree;
+ const QGauss<dim - 1> reference_face_quadrature (2 * superdegree);
+ const unsigned int dofs_per_face = dof_handler.get_fe ().dofs_per_face;
+ hp::FECollection<dim> fe_collection (dof_handler.get_fe ());
+ hp::MappingCollection<dim> mapping_collection (mapping);
+ hp::QCollection<dim> face_quadrature_collection;
+
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ face_quadrature_collection.push_back
+ (QProjector<dim>::project_to_face (reference_face_quadrature, face));
+
+ hp::FEValues<dim> fe_face_values (mapping_collection, fe_collection,
+ face_quadrature_collection,
+ update_jacobians |
+ update_JxW_values |
+ update_quadrature_points |
+ update_values);
+
+ std::vector<double> dof_values (dofs_per_face);
+ std::vector<unsigned int> face_dof_indices (dofs_per_face);
+ typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+
+ switch (dim)
{
- for (; cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
- if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
- return;
-
- // this is only
- // implemented, if the
- // FE is a Nedelec
- // element
- typedef FiniteElement<dim> FEL;
- AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- dof_values[dof] = 0.0;
-
- // Compute the
- // projection of the
- // boundary function on
- // the edge.
- internals::VectorTools
- ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
- boundary_function,
- first_vector_component,
- dof_values);
- cell->face (face)->get_dof_indices (face_dof_indices,
- cell->active_fe_index ());
-
- // Add the computed
- // constraints to the
- // constraint matrix,
- // if the degree of
- // freedom is not
- // already constrained.
- const double tol = 1e-13;
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- if (!(constraints.is_constrained (face_dof_indices[dof])))
- {
- constraints.add_line (face_dof_indices[dof]);
-
- if (std::abs (dof_values[dof]) > tol)
- constraints.set_inhomogeneity (face_dof_indices[dof], dof_values[dof]);
- }
- }
-
- break;
+ case 2:
+ {
+ for (; cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // if the FE is a
+ // FE_Nothing object
+ // there is no work to
+ // do
+ if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
+ return;
+
+ // this is only
+ // implemented, if the
+ // FE is a Nedelec
+ // element
+ typedef FiniteElement<dim> FEL;
+ AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ dof_values[dof] = 0.0;
+
+ // Compute the
+ // projection of the
+ // boundary function on
+ // the edge.
+ internals
+ ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+ cell->face (face)->get_dof_indices (face_dof_indices,
+ cell->active_fe_index ());
+
+ // Add the computed
+ // constraints to the
+ // constraint matrix,
+ // if the degree of
+ // freedom is not
+ // already constrained.
+ const double tol = 1e-13;
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ if (!(constraints.is_constrained (face_dof_indices[dof])))
+ {
+ constraints.add_line (face_dof_indices[dof]);
+
+ if (std::abs (dof_values[dof]) > tol)
+ constraints.set_inhomogeneity (face_dof_indices[dof], dof_values[dof]);
+ }
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ const QGauss<dim - 2> reference_edge_quadrature (2 * superdegree);
+ const unsigned int degree = superdegree - 1;
+ const unsigned int n_dofs = dof_handler.n_dofs ();
+ hp::QCollection<dim> edge_quadrature_collection;
+
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int line = 0; line < GeometryInfo<dim>::lines_per_face; ++line)
+ edge_quadrature_collection.push_back
+ (QProjector<dim>::project_to_face
+ (QProjector<dim - 1>::project_to_face
+ (reference_edge_quadrature, line), face));
+
+ hp::FEValues<dim> fe_edge_values (mapping_collection, fe_collection,
+ edge_quadrature_collection,
+ update_jacobians |
+ update_JxW_values |
+ update_quadrature_points |
+ update_values);
+ std::vector<double> computed_constraints (n_dofs);
+ std::vector<int> projected_dofs (n_dofs);
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof) {
+ computed_constraints[dof] = 0.0;
+ projected_dofs[dof] = -1;
+ }
+
+ for (; cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // if the FE is a
+ // FE_Nothing object
+ // there is no work to
+ // do
+ if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
+ return;
+
+ // this is only
+ // implemented, if the
+ // FE is a Nedelec
+ // element
+ typedef FiniteElement<dim> FEL;
+ AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ dof_values[dof] = 0.0;
+
+ cell->face (face)->get_dof_indices (face_dof_indices,
+ cell->active_fe_index ());
+
+ // First we compute the
+ // projection on the
+ // edges.
+ for (unsigned int line = 0;
+ line < GeometryInfo<3>::lines_per_face; ++line)
+ {
+ // If we have reached
+ // this edge through
+ // another cell
+ // before, we do not
+ // do here anything
+ // unless we have a
+ // good reason, i.e.
+ // a higher
+ // polynomial degree.
+ if (projected_dofs[face_dof_indices[line * superdegree]]
+ <
+ (int) degree)
+ {
+ // Compute the
+ // projection of
+ // the boundary
+ // function on the
+ // edge.
+ internals
+ ::compute_edge_projection (cell, face, line,
+ fe_edge_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+ // Mark the
+ // projected
+ // degrees of
+ // freedom.
+ for (unsigned int dof = line * superdegree;
+ dof < (line + 1) * superdegree; ++dof)
+ projected_dofs[face_dof_indices[dof]] = degree;
+ }
+
+ // If we have
+ // computed the
+ // values in a
+ // previous step of
+ // the loop, we just
+ // copy the values in
+ // the local vector.
+ else
+ for (unsigned int dof = line * superdegree;
+ dof < (line + 1) * superdegree; ++dof)
+ dof_values[dof] = computed_constraints[face_dof_indices[dof]];
+ }
+
+ // If there are higher
+ // order shape
+ // functions, there is
+ // still some work
+ // left.
+ if (degree > 0)
+ {
+ // Compute the
+ // projection of the
+ // boundary function
+ // on the interior of
+ // the face.
+ internals
+ ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+
+ // Mark the projected
+ // degrees of
+ // freedom.
+ for (unsigned int dof = GeometryInfo<dim>::lines_per_face * superdegree;
+ dof < dofs_per_face; ++dof)
+ projected_dofs[face_dof_indices[dof]] = degree;
+ }
+
+ // Store the computed
+ // values in the global
+ // vector.
+ const double tol = 0.5 * superdegree * 1e-13 / cell->face (face)->diameter ();
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ if (std::abs (computed_constraints[face_dof_indices[dof]] - dof_values[dof]) > tol)
+ computed_constraints[face_dof_indices[dof]] = dof_values[dof];
+ }
+
+ // Add the computed constraints
+ // to the constraint matrix, if
+ // the degree of freedom is not
+ // already constrained.
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ if ((projected_dofs[dof] != -1) && !(constraints.is_constrained (dof)))
+ {
+ constraints.add_line (dof);
+ constraints.set_inhomogeneity (dof, computed_constraints[dof]);
+ }
+
+ break;
+ }
+
+ default:
+ Assert (false, ExcNotImplemented ());
}
+ }
+
+
+
+ template <int dim>
+ void
- case 3:
+ project_boundary_values_curl_conforming (const hp::DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const hp::MappingCollection<dim>& mapping_collection)
+ {
+ hp::FECollection<dim> fe_collection (dof_handler.get_fe ());
+ hp::QCollection<dim> face_quadrature_collection;
+
+ for (unsigned int i = 0; i < fe_collection.size (); ++i)
{
- const QGauss<dim - 2> reference_edge_quadrature (2 * superdegree);
- const unsigned int degree = superdegree - 1;
- const unsigned int n_dofs = dof_handler.n_dofs ();
- hp::QCollection<dim> edge_quadrature_collection;
-
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- for (unsigned int line = 0; line < GeometryInfo<dim>::lines_per_face; ++line)
- edge_quadrature_collection.push_back
- (QProjector<dim>::project_to_face
- (QProjector<dim - 1>::project_to_face
- (reference_edge_quadrature, line), face));
-
- hp::FEValues<dim> fe_edge_values (mapping_collection, fe_collection,
- edge_quadrature_collection,
- update_jacobians |
- update_JxW_values |
- update_quadrature_points |
- update_values);
- std::vector<double> computed_constraints (n_dofs);
- std::vector<int> projected_dofs (n_dofs);
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof) {
- computed_constraints[dof] = 0.0;
- projected_dofs[dof] = -1;
- }
-
- for (; cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
- if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
- return;
-
- // this is only
- // implemented, if the
- // FE is a Nedelec
- // element
- typedef FiniteElement<dim> FEL;
- AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- dof_values[dof] = 0.0;
-
- cell->face (face)->get_dof_indices (face_dof_indices,
- cell->active_fe_index ());
-
- // First we compute the
- // projection on the
- // edges.
- for (unsigned int line = 0;
- line < GeometryInfo<3>::lines_per_face; ++line)
- {
- // If we have reached
- // this edge through
- // another cell
- // before, we do not
- // do here anything
- // unless we have a
- // good reason, i.e.
- // a higher
- // polynomial degree.
- if (projected_dofs[face_dof_indices[line * superdegree]]
- <
- (int) degree)
- {
- // Compute the
- // projection of
- // the boundary
- // function on the
- // edge.
- internals::VectorTools
- ::compute_edge_projection (cell, face, line,
- fe_edge_values,
- boundary_function,
- first_vector_component,
- dof_values);
- // Mark the
- // projected
- // degrees of
- // freedom.
- for (unsigned int dof = line * superdegree;
- dof < (line + 1) * superdegree; ++dof)
- projected_dofs[face_dof_indices[dof]] = degree;
- }
-
- // If we have
- // computed the
- // values in a
- // previous step of
- // the loop, we just
- // copy the values in
- // the local vector.
- else
- for (unsigned int dof = line * superdegree;
- dof < (line + 1) * superdegree; ++dof)
- dof_values[dof] = computed_constraints[face_dof_indices[dof]];
- }
-
- // If there are higher
- // order shape
- // functions, there is
- // still some work
- // left.
- if (degree > 0)
- {
- // Compute the
- // projection of the
- // boundary function
- // on the interior of
- // the face.
- internals::VectorTools
- ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
- boundary_function,
- first_vector_component,
- dof_values);
-
- // Mark the projected
- // degrees of
- // freedom.
- for (unsigned int dof = GeometryInfo<dim>::lines_per_face * superdegree;
- dof < dofs_per_face; ++dof)
- projected_dofs[face_dof_indices[dof]] = degree;
- }
-
- // Store the computed
- // values in the global
- // vector.
- const double tol = 0.5 * superdegree * 1e-13 / cell->face (face)->diameter ();
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- if (std::abs (computed_constraints[face_dof_indices[dof]] - dof_values[dof]) > tol)
- computed_constraints[face_dof_indices[dof]] = dof_values[dof];
- }
-
- // Add the computed constraints
- // to the constraint matrix, if
- // the degree of freedom is not
- // already constrained.
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- if ((projected_dofs[dof] != -1) && !(constraints.is_constrained (dof)))
- {
- constraints.add_line (dof);
- constraints.set_inhomogeneity (dof, computed_constraints[dof]);
- }
-
- break;
+ const QGauss<dim - 1>
+ reference_face_quadrature (2 * fe_collection[i].degree);
+
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ face_quadrature_collection.push_back
+ (QProjector<dim>::project_to_face (reference_face_quadrature, face));
}
- default:
- Assert (false, ExcNotImplemented ());
- }
-}
+ hp::FEValues<dim> fe_face_values (mapping_collection, fe_collection,
+ face_quadrature_collection,
+ update_jacobians |
+ update_JxW_values |
+ update_quadrature_points |
+ update_values);
+ std::vector<double> dof_values;
+ std::vector<unsigned int> face_dof_indices;
+ typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+
+ switch (dim)
+ {
+ case 2:
+ {
+ for (; cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // if the FE is a
+ // FE_Nothing object
+ // there is no work to
+ // do
+ if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
+ return;
+
+ // This is only
+ // implemented, if the
+ // FE is a Nedelec
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
+ AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
+ const unsigned int dofs_per_face = cell->get_fe ().dofs_per_face;
-template <int dim>
-void
-VectorTools::
-project_boundary_values_curl_conforming (const hp::DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const hp::MappingCollection<dim>& mapping_collection)
-{
- hp::FECollection<dim> fe_collection (dof_handler.get_fe ());
- hp::QCollection<dim> face_quadrature_collection;
+ dof_values.resize (dofs_per_face);
- for (unsigned int i = 0; i < fe_collection.size (); ++i)
- {
- const QGauss<dim - 1>
- reference_face_quadrature (2 * fe_collection[i].degree);
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ dof_values[dof] = 0.0;
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- face_quadrature_collection.push_back
- (QProjector<dim>::project_to_face (reference_face_quadrature, face));
- }
+ internals
+ ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+ face_dof_indices.resize (dofs_per_face);
+ cell->face (face)->get_dof_indices (face_dof_indices,
+ cell->active_fe_index ());
- hp::FEValues<dim> fe_face_values (mapping_collection, fe_collection,
- face_quadrature_collection,
- update_jacobians |
- update_JxW_values |
- update_quadrature_points |
- update_values);
- std::vector<double> dof_values;
- std::vector<unsigned int> face_dof_indices;
- typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
-
- switch (dim)
- {
- case 2:
- {
- for (; cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
- if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
- return;
-
- // This is only
- // implemented, if the
- // FE is a Nedelec
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- const unsigned int dofs_per_face = cell->get_fe ().dofs_per_face;
-
- dof_values.resize (dofs_per_face);
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- dof_values[dof] = 0.0;
-
- internals::VectorTools
- ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
- boundary_function,
- first_vector_component,
- dof_values);
- face_dof_indices.resize (dofs_per_face);
- cell->face (face)->get_dof_indices (face_dof_indices,
- cell->active_fe_index ());
-
- const double tol = 0.5 * cell->get_fe ().degree * 1e-13 / cell->face (face)->diameter ();
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- if (!(constraints.is_constrained (face_dof_indices[dof])))
- {
- constraints.add_line (face_dof_indices[dof]);
-
- if (std::abs (dof_values[dof]) > tol)
- constraints.set_inhomogeneity (face_dof_indices[dof], dof_values[dof]);
- }
- }
-
- break;
- }
+ const double tol = 0.5 * cell->get_fe ().degree * 1e-13 / cell->face (face)->diameter ();
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ if (!(constraints.is_constrained (face_dof_indices[dof])))
+ {
+ constraints.add_line (face_dof_indices[dof]);
+
+ if (std::abs (dof_values[dof]) > tol)
+ constraints.set_inhomogeneity (face_dof_indices[dof], dof_values[dof]);
+ }
+ }
+
+ break;
+ }
+
+ case 3:
+ {
+ const unsigned int n_dofs = dof_handler.n_dofs ();
+ hp::QCollection<dim> edge_quadrature_collection;
+
+ for (unsigned int i = 0; i < fe_collection.size (); ++i)
+ {
+ const QGauss<dim - 2>
+ reference_edge_quadrature (2 * fe_collection[i].degree);
+
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ for (unsigned int line = 0; line < GeometryInfo<dim>::lines_per_face; ++line)
+ edge_quadrature_collection.push_back
+ (QProjector<dim>::project_to_face
+ (QProjector<dim - 1>::project_to_face (reference_edge_quadrature, line),
+ face));
+ }
+
+ hp::FEValues<dim> fe_edge_values (mapping_collection, fe_collection,
+ edge_quadrature_collection,
+ update_jacobians |
+ update_JxW_values |
+ update_quadrature_points |
+ update_values);
+ std::vector<double> computed_constraints (n_dofs);
+ std::vector<int> projected_dofs (n_dofs);
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof) {
+ computed_constraints[dof] = 0.0;
+ projected_dofs[dof] = -1;
+ }
+
+ for (; cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // if the FE is a
+ // FE_Nothing object
+ // there is no work to
+ // do
+ if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
+ return;
+
+ // This is only
+ // implemented, if the
+ // FE is a Nedelec
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
+
+ AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
+
+ const unsigned int superdegree = cell->get_fe ().degree;
+ const unsigned int degree = superdegree - 1;
+ const unsigned int dofs_per_face = cell->get_fe ().dofs_per_face;
+
+ dof_values.resize (dofs_per_face);
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ dof_values[dof] = 0.0;
+
+ face_dof_indices.resize (dofs_per_face);
+ cell->face (face)->get_dof_indices (face_dof_indices,
+ cell->active_fe_index ());
+
+ for (unsigned int line = 0;
+ line < GeometryInfo<dim>::lines_per_face; ++line)
+ {
+ if (projected_dofs[face_dof_indices[line * superdegree]]
+ <
+ (int) degree)
+ {
+ internals
+ ::compute_edge_projection (cell, face, line,
+ fe_edge_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+
+ for (unsigned int dof = line * superdegree;
+ dof < (line + 1) * superdegree; ++dof)
+ projected_dofs[face_dof_indices[dof]] = degree;
+ }
+
+ else
+ for (unsigned int dof = line * superdegree;
+ dof < (line + 1) * superdegree; ++dof)
+ dof_values[dof] = computed_constraints[face_dof_indices[dof]];
+ }
+
+ if (degree > 0)
+ {
+ internals
+ ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
+ boundary_function,
+ first_vector_component,
+ dof_values);
+
+ for (unsigned int dof = GeometryInfo<dim>::lines_per_face * superdegree;
+ dof < dofs_per_face; ++dof)
+ projected_dofs[face_dof_indices[dof]] = degree;
+ }
+
+ const double tol = 0.5 * superdegree * 1e-13 / cell->face (face)->diameter ();
+
+ for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
+ if (std::abs (computed_constraints[face_dof_indices[dof]] - dof_values[dof]) > tol)
+ computed_constraints[face_dof_indices[dof]] = dof_values[dof];
+ }
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ if ((projected_dofs[dof] != -1) && !(constraints.is_constrained (dof)))
+ {
+ constraints.add_line (dof);
+ constraints.set_inhomogeneity (dof, computed_constraints[dof]);
+ }
+
+ break;
+ }
- case 3:
- {
- const unsigned int n_dofs = dof_handler.n_dofs ();
- hp::QCollection<dim> edge_quadrature_collection;
-
- for (unsigned int i = 0; i < fe_collection.size (); ++i)
- {
- const QGauss<dim - 2>
- reference_edge_quadrature (2 * fe_collection[i].degree);
-
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- for (unsigned int line = 0; line < GeometryInfo<dim>::lines_per_face; ++line)
- edge_quadrature_collection.push_back
- (QProjector<dim>::project_to_face
- (QProjector<dim - 1>::project_to_face (reference_edge_quadrature, line),
- face));
- }
-
- hp::FEValues<dim> fe_edge_values (mapping_collection, fe_collection,
- edge_quadrature_collection,
- update_jacobians |
- update_JxW_values |
- update_quadrature_points |
- update_values);
- std::vector<double> computed_constraints (n_dofs);
- std::vector<int> projected_dofs (n_dofs);
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof) {
- computed_constraints[dof] = 0.0;
- projected_dofs[dof] = -1;
- }
-
- for (; cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
- if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
- return;
-
- // This is only
- // implemented, if the
- // FE is a Nedelec
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_Nedelec<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- const unsigned int superdegree = cell->get_fe ().degree;
- const unsigned int degree = superdegree - 1;
- const unsigned int dofs_per_face = cell->get_fe ().dofs_per_face;
-
- dof_values.resize (dofs_per_face);
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- dof_values[dof] = 0.0;
-
- face_dof_indices.resize (dofs_per_face);
- cell->face (face)->get_dof_indices (face_dof_indices,
- cell->active_fe_index ());
-
- for (unsigned int line = 0;
- line < GeometryInfo<dim>::lines_per_face; ++line)
- {
- if (projected_dofs[face_dof_indices[line * superdegree]]
- <
- (int) degree)
- {
- internals::VectorTools
- ::compute_edge_projection (cell, face, line,
- fe_edge_values,
- boundary_function,
- first_vector_component,
- dof_values);
-
- for (unsigned int dof = line * superdegree;
- dof < (line + 1) * superdegree; ++dof)
- projected_dofs[face_dof_indices[dof]] = degree;
- }
-
- else
- for (unsigned int dof = line * superdegree;
- dof < (line + 1) * superdegree; ++dof)
- dof_values[dof] = computed_constraints[face_dof_indices[dof]];
- }
-
- if (degree > 0)
- {
- internals::VectorTools
- ::compute_face_projection_curl_conforming (cell, face, fe_face_values,
- boundary_function,
- first_vector_component,
- dof_values);
-
- for (unsigned int dof = GeometryInfo<dim>::lines_per_face * superdegree;
- dof < dofs_per_face; ++dof)
- projected_dofs[face_dof_indices[dof]] = degree;
- }
-
- const double tol = 0.5 * superdegree * 1e-13 / cell->face (face)->diameter ();
-
- for (unsigned int dof = 0; dof < dofs_per_face; ++dof)
- if (std::abs (computed_constraints[face_dof_indices[dof]] - dof_values[dof]) > tol)
- computed_constraints[face_dof_indices[dof]] = dof_values[dof];
- }
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- if ((projected_dofs[dof] != -1) && !(constraints.is_constrained (dof)))
- {
- constraints.add_line (dof);
- constraints.set_inhomogeneity (dof, computed_constraints[dof]);
- }
-
- break;
+ default:
+ Assert (false, ExcNotImplemented ());
}
-
- default:
- Assert (false, ExcNotImplemented ());
- }
-}
+ }
-namespace internals {
- namespace VectorTools {
- // This function computes the
- // projection of the boundary
- // function on the boundary
- // in 2d.
+ namespace internals
+ {
+ // This function computes the
+ // projection of the boundary
+ // function on the boundary
+ // in 2d.
template <typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator& cell,
- const unsigned int face,
- const FEFaceValues<2>& fe_values,
- const unsigned int first_vector_component,
- const Function<2>& boundary_function,
- const std::vector<Tensor<2, 2> >& jacobians,
- ConstraintMatrix& constraints)
+ const unsigned int face,
+ const FEFaceValues<2>& fe_values,
+ const unsigned int first_vector_component,
+ const Function<2>& boundary_function,
+ const std::vector<Tensor<2, 2> >& jacobians,
+ ConstraintMatrix& constraints)
{
- // Compute the intergral over
- // the product of the normal
- // components of the boundary
- // function times the normal
- // components of the shape
- // functions supported on the
- // boundary.
+ // Compute the intergral over
+ // the product of the normal
+ // components of the boundary
+ // function times the normal
+ // components of the shape
+ // functions supported on the
+ // boundary.
const FEValuesExtractors::Vector vec (first_vector_component);
const FiniteElement<2>& fe = cell->get_fe ();
const std::vector<Point<2> >& normals = fe_values.get_normal_vectors ();
const unsigned int
- face_coordinate_direction[GeometryInfo<2>::faces_per_cell] = {1, 1, 0, 0};
+ face_coordinate_direction[GeometryInfo<2>::faces_per_cell] = {1, 1, 0, 0};
std::vector<Vector<double> >
- values (fe_values.n_quadrature_points, Vector<double> (2));
+ values (fe_values.n_quadrature_points, Vector<double> (2));
Vector<double> dof_values (fe.dofs_per_face);
- // Get the values of the
- // boundary function at the
- // quadrature points.
+ // Get the values of the
+ // boundary function at the
+ // quadrature points.
{
- const std::vector<Point<2> >&
- quadrature_points = fe_values.get_quadrature_points ();
+ const std::vector<Point<2> >&
+ quadrature_points = fe_values.get_quadrature_points ();
- boundary_function.vector_value_list (quadrature_points, values);
+ boundary_function.vector_value_list (quadrature_points, values);
}
for (unsigned int q_point = 0; q_point < fe_values.n_quadrature_points; ++q_point)
- {
- double tmp = 0.0;
+ {
+ double tmp = 0.0;
- for (unsigned int d = 0; d < 2; ++d)
- tmp += normals[q_point][d] * values[q_point] (d);
+ for (unsigned int d = 0; d < 2; ++d)
+ tmp += normals[q_point][d] * values[q_point] (d);
- tmp *= fe_values.JxW (q_point)
- * std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
- * jacobians[q_point][0][face_coordinate_direction[face]]
- + jacobians[q_point][1][face_coordinate_direction[face]]
- * jacobians[q_point][1][face_coordinate_direction[face]]);
+ tmp *= fe_values.JxW (q_point)
+ * std::sqrt (jacobians[q_point][0][face_coordinate_direction[face]]
+ * jacobians[q_point][0][face_coordinate_direction[face]]
+ + jacobians[q_point][1][face_coordinate_direction[face]]
+ * jacobians[q_point][1][face_coordinate_direction[face]]);
- for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
- dof_values (i) += tmp * (normals[q_point]
- * fe_values[vec].value (fe.face_to_cell_index (i, face), q_point));
- }
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ dof_values (i) += tmp * (normals[q_point]
+ * fe_values[vec].value (fe.face_to_cell_index (i, face), q_point));
+ }
std::vector<unsigned int> face_dof_indices (fe.dofs_per_face);
cell->face (face)->get_dof_indices (face_dof_indices, cell->active_fe_index ());
- // Copy the computed values
- // in the ConstraintMatrix only,
- // if the degree of freedom is
- // not already constrained.
+ // Copy the computed values
+ // in the ConstraintMatrix only,
+ // if the degree of freedom is
+ // not already constrained.
for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
- if (!(constraints.is_constrained (face_dof_indices[i])))
- {
- constraints.add_line (face_dof_indices[i]);
+ if (!(constraints.is_constrained (face_dof_indices[i])))
+ {
+ constraints.add_line (face_dof_indices[i]);
- if (std::abs (dof_values (i)) > 1e-14)
- constraints.set_inhomogeneity (face_dof_indices[i], dof_values (i));
- }
+ if (std::abs (dof_values (i)) > 1e-14)
+ constraints.set_inhomogeneity (face_dof_indices[i], dof_values (i));
+ }
}
- // dummy implementation of above
- // function for all other
- // dimensions
+ // dummy implementation of above
+ // function for all other
+ // dimensions
template<int dim, typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator&,
- const unsigned int,
- const FEFaceValues<dim>&,
- const unsigned int,
- const Function<dim>&,
- const std::vector<Tensor<2, dim> >&,
- ConstraintMatrix&)
+ const unsigned int,
+ const FEFaceValues<dim>&,
+ const unsigned int,
+ const Function<dim>&,
+ const std::vector<Tensor<2, dim> >&,
+ ConstraintMatrix&)
{
Assert (false, ExcNotImplemented ());
}
- // This function computes the
- // projection of the boundary
- // function on the boundary
- // in 3d.
+ // This function computes the
+ // projection of the boundary
+ // function on the boundary
+ // in 3d.
template<typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator& cell,
- const unsigned int face,
- const FEFaceValues<3>& fe_values,
- const unsigned int first_vector_component,
- const Function<3>& boundary_function,
- const std::vector<Tensor<2, 3> >& jacobians,
- std::vector<double>& dof_values,
- std::vector<unsigned int>& projected_dofs)
+ const unsigned int face,
+ const FEFaceValues<3>& fe_values,
+ const unsigned int first_vector_component,
+ const Function<3>& boundary_function,
+ const std::vector<Tensor<2, 3> >& jacobians,
+ std::vector<double>& dof_values,
+ std::vector<unsigned int>& projected_dofs)
{
- // Compute the intergral over
- // the product of the normal
- // components of the boundary
- // function times the normal
- // components of the shape
- // functions supported on the
- // boundary.
+ // Compute the intergral over
+ // the product of the normal
+ // components of the boundary
+ // function times the normal
+ // components of the shape
+ // functions supported on the
+ // boundary.
const FEValuesExtractors::Vector vec (first_vector_component);
const FiniteElement<3>& fe = cell->get_fe ();
const std::vector<Point<3> >& normals = fe_values.get_normal_vectors ();
const unsigned int
- face_coordinate_directions[GeometryInfo<3>::faces_per_cell][2] = {{1, 2},
- {1, 2},
- {2, 0},
- {2, 0},
- {0, 1},
- {0, 1}};
+ face_coordinate_directions[GeometryInfo<3>::faces_per_cell][2] = {{1, 2},
+ {1, 2},
+ {2, 0},
+ {2, 0},
+ {0, 1},
+ {0, 1}};
std::vector<Vector<double> >
- values (fe_values.n_quadrature_points, Vector<double> (3));
+ values (fe_values.n_quadrature_points, Vector<double> (3));
Vector<double> dof_values_local (fe.dofs_per_face);
{
- const std::vector<Point<3> >&
- quadrature_points = fe_values.get_quadrature_points ();
+ const std::vector<Point<3> >&
+ quadrature_points = fe_values.get_quadrature_points ();
- boundary_function.vector_value_list (quadrature_points, values);
+ boundary_function.vector_value_list (quadrature_points, values);
}
for (unsigned int q_point = 0; q_point < fe_values.n_quadrature_points; ++q_point)
- {
- double tmp = 0.0;
-
- for (unsigned int d = 0; d < 3; ++d)
- tmp += normals[q_point][d] * values[q_point] (d);
-
- tmp *= fe_values.JxW (q_point)
- * std::sqrt ((jacobians[q_point][0][face_coordinate_directions[face][0]]
- * jacobians[q_point][0][face_coordinate_directions[face][0]]
- + jacobians[q_point][1][face_coordinate_directions[face][0]]
- * jacobians[q_point][1][face_coordinate_directions[face][0]]
- + jacobians[q_point][2][face_coordinate_directions[face][0]]
- * jacobians[q_point][2][face_coordinate_directions[face][0]])
- * (jacobians[q_point][0][face_coordinate_directions[face][1]]
- * jacobians[q_point][0][face_coordinate_directions[face][1]]
- + jacobians[q_point][1][face_coordinate_directions[face][1]]
- * jacobians[q_point][1][face_coordinate_directions[face][1]]
- + jacobians[q_point][2][face_coordinate_directions[face][1]]
- * jacobians[q_point][2][face_coordinate_directions[face][1]]));
-
- for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
- dof_values_local (i) += tmp * (normals[q_point]
- * fe_values[vec].value (fe.face_to_cell_index (i, face), q_point));
- }
+ {
+ double tmp = 0.0;
+
+ for (unsigned int d = 0; d < 3; ++d)
+ tmp += normals[q_point][d] * values[q_point] (d);
+
+ tmp *= fe_values.JxW (q_point)
+ * std::sqrt ((jacobians[q_point][0][face_coordinate_directions[face][0]]
+ * jacobians[q_point][0][face_coordinate_directions[face][0]]
+ + jacobians[q_point][1][face_coordinate_directions[face][0]]
+ * jacobians[q_point][1][face_coordinate_directions[face][0]]
+ + jacobians[q_point][2][face_coordinate_directions[face][0]]
+ * jacobians[q_point][2][face_coordinate_directions[face][0]])
+ * (jacobians[q_point][0][face_coordinate_directions[face][1]]
+ * jacobians[q_point][0][face_coordinate_directions[face][1]]
+ + jacobians[q_point][1][face_coordinate_directions[face][1]]
+ * jacobians[q_point][1][face_coordinate_directions[face][1]]
+ + jacobians[q_point][2][face_coordinate_directions[face][1]]
+ * jacobians[q_point][2][face_coordinate_directions[face][1]]));
+
+ for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
+ dof_values_local (i) += tmp * (normals[q_point]
+ * fe_values[vec].value (fe.face_to_cell_index (i, face), q_point));
+ }
std::vector<unsigned int> face_dof_indices (fe.dofs_per_face);
cell->face (face)->get_dof_indices (face_dof_indices, cell->active_fe_index ());
for (unsigned int i = 0; i < fe.dofs_per_face; ++i)
- if (projected_dofs[face_dof_indices[i]] < fe.degree)
- {
- dof_values[face_dof_indices[i]] = dof_values_local (i);
- projected_dofs[face_dof_indices[i]] = fe.degree;
- }
+ if (projected_dofs[face_dof_indices[i]] < fe.degree)
+ {
+ dof_values[face_dof_indices[i]] = dof_values_local (i);
+ projected_dofs[face_dof_indices[i]] = fe.degree;
+ }
}
- // dummy implementation of above
- // function for all other
- // dimensions
+ // dummy implementation of above
+ // function for all other
+ // dimensions
template<int dim, typename cell_iterator>
void
compute_face_projection_div_conforming (const cell_iterator&,
- const unsigned int,
- const FEFaceValues<dim>&,
- const unsigned int,
- const Function<dim>&,
- const std::vector<Tensor<2, dim> >&,
- std::vector<double>&,
- std::vector<unsigned int>&)
+ const unsigned int,
+ const FEFaceValues<dim>&,
+ const unsigned int,
+ const Function<dim>&,
+ const std::vector<Tensor<2, dim> >&,
+ std::vector<double>&,
+ std::vector<unsigned int>&)
{
Assert (false, ExcNotImplemented ());
}
}
-}
-template <int dim>
-void
-VectorTools::project_boundary_values_div_conforming (const DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const Mapping<dim>& mapping)
-{
- // Interpolate the normal components
- // of the boundary functions. Since
- // the Raviart-Thomas elements are
- // constructed from a Lagrangian
- // basis, it suffices to compute
- // the integral over the product
- // of the normal components of the
- // boundary function times the
- // normal components of the shape
- // functions supported on the
- // boundary.
- const FiniteElement<dim>& fe = dof_handler.get_fe ();
- QGauss<dim - 1> face_quadrature (fe.degree + 1);
- FEFaceValues<dim> fe_face_values (mapping, fe, face_quadrature, update_JxW_values |
- update_normal_vectors |
- update_quadrature_points |
- update_values);
- hp::FECollection<dim> fe_collection (fe);
- hp::MappingCollection<dim> mapping_collection (mapping);
- hp::QCollection<dim> quadrature_collection;
-
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- quadrature_collection.push_back (QProjector<dim>::project_to_face (face_quadrature,
- face));
-
- hp::FEValues<dim> fe_values (mapping_collection, fe_collection, quadrature_collection,
- update_jacobians);
-
- switch (dim)
+ template <int dim>
+ void
+ project_boundary_values_div_conforming (const DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const Mapping<dim>& mapping)
{
- case 2:
- {
- for (typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
- cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // if the FE is a
- // FE_Nothing object
- // there is no work to
- // do
- if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
- return;
-
- // This is only
- // implemented, if the
- // FE is a Raviart-Thomas
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- fe_values.reinit (cell, face + cell->active_fe_index ()
- * GeometryInfo<dim>::faces_per_cell);
-
- const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_present_fe_values ().get_jacobians ();
-
- fe_face_values.reinit (cell, face);
- internals::VectorTools::compute_face_projection_div_conforming (cell, face,
- fe_face_values,
- first_vector_component,
- boundary_function,
- jacobians,
- constraints);
- }
-
- break;
- }
+ // Interpolate the normal components
+ // of the boundary functions. Since
+ // the Raviart-Thomas elements are
+ // constructed from a Lagrangian
+ // basis, it suffices to compute
+ // the integral over the product
+ // of the normal components of the
+ // boundary function times the
+ // normal components of the shape
+ // functions supported on the
+ // boundary.
+ const FiniteElement<dim>& fe = dof_handler.get_fe ();
+ QGauss<dim - 1> face_quadrature (fe.degree + 1);
+ FEFaceValues<dim> fe_face_values (mapping, fe, face_quadrature, update_JxW_values |
+ update_normal_vectors |
+ update_quadrature_points |
+ update_values);
+ hp::FECollection<dim> fe_collection (fe);
+ hp::MappingCollection<dim> mapping_collection (mapping);
+ hp::QCollection<dim> quadrature_collection;
- case 3:
- {
- // In three dimensions the
- // edges between two faces
- // are treated twice.
- // Therefore we store the
- // computed values in a
- // vector and copy them over
- // in the ConstraintMatrix
- // after all values have been
- // computed.
- // If we have two values for
- // one edge, we choose the one,
- // which was computed with the
- // higher order element.
- // If both elements are of the
- // same order, we just keep the
- // first value and do not
- // compute a second one.
- const unsigned int& n_dofs = dof_handler.n_dofs ();
- std::vector<double> dof_values (n_dofs);
- std::vector<unsigned int> projected_dofs (n_dofs);
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- projected_dofs[dof] = 0;
-
- for (typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
- cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // This is only
- // implemented, if the
- // FE is a Raviart-Thomas
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- fe_values.reinit (cell, face + cell->active_fe_index ()
- * GeometryInfo<dim>::faces_per_cell);
-
- const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_present_fe_values ().get_jacobians ();
-
- fe_face_values.reinit (cell, face);
- internals::VectorTools::compute_face_projection_div_conforming (cell, face,
- fe_face_values,
- first_vector_component,
- boundary_function,
- jacobians, dof_values,
- projected_dofs);
- }
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- if ((projected_dofs[dof] != 0) && !(constraints.is_constrained (dof)))
- {
- constraints.add_line (dof);
-
- if (std::abs (dof_values[dof]) > 1e-14)
- constraints.set_inhomogeneity (dof, dof_values[dof]);
- }
-
- break;
- }
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ quadrature_collection.push_back (QProjector<dim>::project_to_face (face_quadrature,
+ face));
- default:
- Assert (false, ExcNotImplemented ());
- }
-}
+ hp::FEValues<dim> fe_values (mapping_collection, fe_collection, quadrature_collection,
+ update_jacobians);
+
+ switch (dim)
+ {
+ case 2:
+ {
+ for (typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+ cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // if the FE is a
+ // FE_Nothing object
+ // there is no work to
+ // do
+ if (dynamic_cast<const FE_Nothing<dim>*> (&cell->get_fe ()) != 0)
+ return;
+
+ // This is only
+ // implemented, if the
+ // FE is a Raviart-Thomas
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
+ AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
-template <int dim>
-void
-VectorTools::project_boundary_values_div_conforming (const hp::DoFHandler<dim>& dof_handler,
- const unsigned int first_vector_component,
- const Function<dim>& boundary_function,
- const unsigned char boundary_component,
- ConstraintMatrix& constraints,
- const hp::MappingCollection<dim, dim>& mapping_collection)
-{
- const hp::FECollection<dim>& fe_collection = dof_handler.get_fe ();
- hp::QCollection<dim - 1> face_quadrature_collection;
- hp::QCollection<dim> quadrature_collection;
+ fe_values.reinit (cell, face + cell->active_fe_index ()
+ * GeometryInfo<dim>::faces_per_cell);
- for (unsigned int i = 0; i < fe_collection.size (); ++i)
- {
- const QGauss<dim - 1> quadrature (fe_collection[i].degree + 1);
+ const std::vector<Tensor<2, dim> >&
+ jacobians = fe_values.get_present_fe_values ().get_jacobians ();
- face_quadrature_collection.push_back (quadrature);
+ fe_face_values.reinit (cell, face);
+ internals::compute_face_projection_div_conforming (cell, face,
+ fe_face_values,
+ first_vector_component,
+ boundary_function,
+ jacobians,
+ constraints);
+ }
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- quadrature_collection.push_back (QProjector<dim>::project_to_face (quadrature,
- face));
- }
+ break;
+ }
- hp::FEFaceValues<dim> fe_face_values (mapping_collection, fe_collection,
- face_quadrature_collection, update_JxW_values |
- update_normal_vectors |
- update_quadrature_points |
- update_values);
- hp::FEValues<dim> fe_values (mapping_collection, fe_collection, quadrature_collection,
- update_jacobians);
+ case 3:
+ {
+ // In three dimensions the
+ // edges between two faces
+ // are treated twice.
+ // Therefore we store the
+ // computed values in a
+ // vector and copy them over
+ // in the ConstraintMatrix
+ // after all values have been
+ // computed.
+ // If we have two values for
+ // one edge, we choose the one,
+ // which was computed with the
+ // higher order element.
+ // If both elements are of the
+ // same order, we just keep the
+ // first value and do not
+ // compute a second one.
+ const unsigned int& n_dofs = dof_handler.n_dofs ();
+ std::vector<double> dof_values (n_dofs);
+ std::vector<unsigned int> projected_dofs (n_dofs);
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ projected_dofs[dof] = 0;
+
+ for (typename DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+ cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // This is only
+ // implemented, if the
+ // FE is a Raviart-Thomas
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
- switch (dim)
- {
- case 2:
- {
- for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
- cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // This is only
- // implemented, if the
- // FE is a Raviart-Thomas
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- fe_values.reinit (cell, face + cell->active_fe_index ()
- * GeometryInfo<dim>::faces_per_cell);
-
- const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_present_fe_values ().get_jacobians ();
-
- fe_face_values.reinit (cell, face);
- internals::VectorTools::compute_face_projection_div_conforming (cell, face,
- fe_face_values.get_present_fe_values (),
- first_vector_component,
- boundary_function,
- jacobians,
- constraints);
- }
-
- break;
- }
+ AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
- case 3:
- {
- const unsigned int& n_dofs = dof_handler.n_dofs ();
- std::vector<double> dof_values (n_dofs);
- std::vector<unsigned int> projected_dofs (n_dofs);
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- projected_dofs[dof] = 0;
-
- for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
- cell != dof_handler.end (); ++cell)
- if (cell->at_boundary ())
- for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face (face)->boundary_indicator () == boundary_component)
- {
- // This is only
- // implemented, if the
- // FE is a Raviart-Thomas
- // element. If the FE is
- // a FESystem we cannot
- // check this.
- if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
- {
- typedef FiniteElement<dim> FEL;
-
- AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
- typename FEL::ExcInterpolationNotImplemented ());
- }
-
- fe_values.reinit (cell, face + cell->active_fe_index ()
- * GeometryInfo<dim>::faces_per_cell);
-
- const std::vector<Tensor<2, dim> >&
- jacobians = fe_values.get_present_fe_values ().get_jacobians ();
-
- fe_face_values.reinit (cell, face);
- internals::VectorTools::compute_face_projection_div_conforming (cell, face,
- fe_face_values.get_present_fe_values (),
- first_vector_component,
- boundary_function,
- jacobians, dof_values,
- projected_dofs);
- }
-
- for (unsigned int dof = 0; dof < n_dofs; ++dof)
- if ((projected_dofs[dof] != 0) && !(constraints.is_constrained (dof)))
- {
- constraints.add_line (dof);
-
- if (std::abs (dof_values[dof]) > 1e-14)
- constraints.set_inhomogeneity (dof, dof_values[dof]);
- }
-
- break;
- }
+ fe_values.reinit (cell, face + cell->active_fe_index ()
+ * GeometryInfo<dim>::faces_per_cell);
- default:
- Assert (false, ExcNotImplemented ());
+ const std::vector<Tensor<2, dim> >&
+ jacobians = fe_values.get_present_fe_values ().get_jacobians ();
+
+ fe_face_values.reinit (cell, face);
+ internals::compute_face_projection_div_conforming (cell, face,
+ fe_face_values,
+ first_vector_component,
+ boundary_function,
+ jacobians, dof_values,
+ projected_dofs);
+ }
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ if ((projected_dofs[dof] != 0) && !(constraints.is_constrained (dof)))
+ {
+ constraints.add_line (dof);
+
+ if (std::abs (dof_values[dof]) > 1e-14)
+ constraints.set_inhomogeneity (dof, dof_values[dof]);
+ }
+
+ break;
+ }
+
+ default:
+ Assert (false, ExcNotImplemented ());
+ }
}
-}
-template <int dim, template <int, int> class DH, int spacedim>
-void
-VectorTools::
-compute_no_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
- const unsigned int first_vector_component,
- const std::set<unsigned char> &boundary_ids,
- ConstraintMatrix &constraints,
- const Mapping<dim, spacedim> &mapping)
-{
- Assert (dim > 1,
- ExcMessage ("This function is not useful in 1d because it amounts "
- "to imposing Dirichlet values on the vector-valued "
- "quantity."));
-
- std::vector<unsigned int> face_dofs;
-
- // create FE and mapping
- // collections for all elements in
- // use by this DoFHandler
- hp::FECollection<dim,spacedim> fe_collection (dof_handler.get_fe());
- hp::MappingCollection<dim,spacedim> mapping_collection;
- for (unsigned int i=0; i<fe_collection.size(); ++i)
- mapping_collection.push_back (mapping);
-
- // now also create a quadrature
- // collection for the faces of a
- // cell. fill it with a quadrature
- // formula with the support points
- // on faces for each FE
- hp::QCollection<dim-1> face_quadrature_collection;
- for (unsigned int i=0; i<fe_collection.size(); ++i)
- {
- const std::vector<Point<dim-1> > &
- unit_support_points = fe_collection[i].get_unit_face_support_points();
+ template <int dim>
+ void
+ project_boundary_values_div_conforming (const hp::DoFHandler<dim>& dof_handler,
+ const unsigned int first_vector_component,
+ const Function<dim>& boundary_function,
+ const unsigned char boundary_component,
+ ConstraintMatrix& constraints,
+ const hp::MappingCollection<dim, dim>& mapping_collection)
+ {
+ const hp::FECollection<dim>& fe_collection = dof_handler.get_fe ();
+ hp::QCollection<dim - 1> face_quadrature_collection;
+ hp::QCollection<dim> quadrature_collection;
- Assert (unit_support_points.size() == fe_collection[i].dofs_per_face,
- ExcInternalError());
+ for (unsigned int i = 0; i < fe_collection.size (); ++i)
+ {
+ const QGauss<dim - 1> quadrature (fe_collection[i].degree + 1);
- face_quadrature_collection
- .push_back (Quadrature<dim-1> (unit_support_points));
- }
+ face_quadrature_collection.push_back (quadrature);
- // now create the object with which
- // we will generate the normal
- // vectors
- hp::FEFaceValues<dim,spacedim> x_fe_face_values (mapping_collection,
- fe_collection,
- face_quadrature_collection,
- update_q_points);
-
- // have a map that stores normal
- // vectors for each vector-dof
- // tuple we want to
- // constrain. since we can get at
- // the same vector dof tuple more
- // than once (for example if it is
- // located at a vertex that we
- // visit from all adjacent cells),
- // we will want to average later on
- // the normal vectors computed on
- // different cells as described in
- // the documentation of this
- // function. however, we can only
- // average if the contributions
- // came from different cells,
- // whereas we want to constrain
- // twice or more in case the
- // contributions came from
- // different faces of the same cell
- // (i.e. constrain not just the
- // *average normal direction* but
- // *all normal directions* we
- // find). consequently, we also
- // have to store which cell a
- // normal vector was computed on
- typedef
- std::multimap<internal::VectorTools::VectorDoFTuple<dim>,
- std::pair<Tensor<1,dim>, typename DH<dim,spacedim>::active_cell_iterator> >
- DoFToNormalsMap;
-
- DoFToNormalsMap dof_to_normals_map;
-
- // now loop over all cells and all faces
- typename DH<dim,spacedim>::active_cell_iterator
- cell = dof_handler.begin_active(),
- endc = dof_handler.end();
- for (; cell!=endc; ++cell)
- if (!cell->is_artificial())
- for (unsigned int face_no=0; face_no < GeometryInfo<dim>::faces_per_cell;
- ++face_no)
- if (boundary_ids.find(cell->face(face_no)->boundary_indicator())
- != boundary_ids.end())
- {
- const FiniteElement<dim>& fe = cell->get_fe ();
- typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
-
- // get the indices of the
- // dofs on this cell...
- face_dofs.resize (fe.dofs_per_face);
- face->get_dof_indices (face_dofs, cell->active_fe_index());
-
- x_fe_face_values.reinit (cell, face_no);
- const FEFaceValues<dim> &fe_values = x_fe_face_values.get_present_fe_values();
-
- // then identify which of
- // them correspond to the
- // selected set of vector
- // components
- for (unsigned int i=0; i<face_dofs.size(); ++i)
- if (fe.face_system_to_component_index(i).first ==
- first_vector_component)
- {
- // find corresponding other
- // components of vector
- internal::VectorTools::VectorDoFTuple<dim> vector_dofs;
- vector_dofs.dof_indices[0] = face_dofs[i];
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ quadrature_collection.push_back (QProjector<dim>::project_to_face (quadrature,
+ face));
+ }
- for (unsigned int k=0; k<fe.dofs_per_face; ++k)
- if ((k != i)
- &&
- (face_quadrature_collection[cell->active_fe_index()].point(k) ==
- face_quadrature_collection[cell->active_fe_index()].point(i))
- &&
- (fe.face_system_to_component_index(k).first >=
- first_vector_component)
- &&
- (fe.face_system_to_component_index(k).first <
- first_vector_component + dim))
- vector_dofs.dof_indices[fe.face_system_to_component_index(k).first -
- first_vector_component]
- = face_dofs[k];
+ hp::FEFaceValues<dim> fe_face_values (mapping_collection, fe_collection,
+ face_quadrature_collection, update_JxW_values |
+ update_normal_vectors |
+ update_quadrature_points |
+ update_values);
+ hp::FEValues<dim> fe_values (mapping_collection, fe_collection, quadrature_collection,
+ update_jacobians);
- for (unsigned int d=0; d<dim; ++d)
- Assert (vector_dofs.dof_indices[d] < dof_handler.n_dofs(),
- ExcInternalError());
+ switch (dim)
+ {
+ case 2:
+ {
+ for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+ cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // This is only
+ // implemented, if the
+ // FE is a Raviart-Thomas
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
- // we need the normal
- // vector on this face. we
- // know that it is a vector
- // of length 1 but at least
- // with higher order
- // mappings it isn't always
- // possible to guarantee
- // that each component is
- // exact up to zero
- // tolerance. in
- // particular, as shown in
- // the deal.II/no_flux_06
- // test, if we just take
- // the normal vector as
- // given by the fe_values
- // object, we can get
- // entries in the normal
- // vectors of the unit cube
- // that have entries up to
- // several times 1e-14.
- //
- // the problem with this is
- // that this later yields
- // constraints that are
- // circular (e.g., in the
- // testcase, we get
- // constraints of the form
- //
- // x22 = 2.93099e-14*x21 + 2.93099e-14*x23
- // x21 = -2.93099e-14*x22 + 2.93099e-14*x21
- //
- // in both of these
- // constraints, the small
- // numbers should be zero
- // and the constraints
- // should simply be
- // x22 = x21 = 0
- //
- // to achieve this, we
- // utilize that we know
- // that the normal vector
- // has (or should have)
- // length 1 and that we can
- // simply set small
- // elements to zero
- // (without having to check
- // that they are small
- // *relative to something
- // else*). we do this and
- // then normalize the
- // length of the vector
- // back to one, just to be
- // on the safe side
- Point<dim> normal_vector
- = (cell->face(face_no)->get_boundary()
- .normal_vector (cell->face(face_no),
- fe_values.quadrature_point(i)));
- Assert (std::fabs(normal_vector.norm() - 1) < 1e-14,
- ExcInternalError());
- for (unsigned int d=0; d<dim; ++d)
- if (std::fabs(normal_vector[d]) < 1e-13)
- normal_vector[d] = 0;
- normal_vector /= normal_vector.norm();
-
- // now enter the
- // (dofs,(normal_vector,cell))
- // entry into the map
- dof_to_normals_map
- .insert (std::make_pair (vector_dofs,
- std::make_pair (normal_vector,
- cell)));
- }
- }
+ AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
- // Now do something with the
- // collected information. To this
- // end, loop through all sets of
- // pairs (dofs,normal_vector) and
- // identify which entries belong to
- // the same set of dofs and then do
- // as described in the
- // documentation, i.e. either
- // average the normal vector or
- // don't for this particular set of
- // dofs
- typename DoFToNormalsMap::const_iterator
- p = dof_to_normals_map.begin();
-
- while (p != dof_to_normals_map.end())
- {
- // first find the range of entries in
- // the multimap that corresponds to the
- // same vector-dof tuple. as usual, we
- // define the range half-open. the
- // first entry of course is 'p'
- typename DoFToNormalsMap::const_iterator same_dof_range[2]
- = { p };
- for (++p; p != dof_to_normals_map.end(); ++p)
- if (p->first != same_dof_range[0]->first)
- {
- same_dof_range[1] = p;
- break;
- }
- if (p == dof_to_normals_map.end())
- same_dof_range[1] = dof_to_normals_map.end();
-
- // now compute the reverse mapping: for
- // each of the cells that contributed
- // to the current set of vector dofs,
- // add up the normal vectors. the
- // values of the map are pairs of
- // normal vectors and number of cells
- // that have contributed
- typedef
- std::map
- <typename DH<dim,spacedim>::active_cell_iterator,
- std::pair<Tensor<1,dim>, unsigned int> >
- CellToNormalsMap;
-
- CellToNormalsMap cell_to_normals_map;
- for (typename DoFToNormalsMap::const_iterator
- q = same_dof_range[0];
- q != same_dof_range[1]; ++q)
- if (cell_to_normals_map.find (q->second.second)
- == cell_to_normals_map.end())
- cell_to_normals_map[q->second.second]
- = std::make_pair (q->second.first, 1U);
- else
- {
- const Tensor<1,dim> old_normal
- = cell_to_normals_map[q->second.second].first;
- const unsigned int old_count
- = cell_to_normals_map[q->second.second].second;
+ fe_values.reinit (cell, face + cell->active_fe_index ()
+ * GeometryInfo<dim>::faces_per_cell);
- Assert (old_count > 0, ExcInternalError());
+ const std::vector<Tensor<2, dim> >&
+ jacobians = fe_values.get_present_fe_values ().get_jacobians ();
- // in the same entry,
- // store again the now
- // averaged normal vector
- // and the new count
- cell_to_normals_map[q->second.second]
- = std::make_pair ((old_normal * old_count + q->second.first) / (old_count + 1),
- old_count + 1);
- }
+ fe_face_values.reinit (cell, face);
+ internals::compute_face_projection_div_conforming (cell, face,
+ fe_face_values.get_present_fe_values (),
+ first_vector_component,
+ boundary_function,
+ jacobians,
+ constraints);
+ }
+
+ break;
+ }
- Assert (cell_to_normals_map.size() >= 1, ExcInternalError());
-
- // count the maximum number of
- // contributions from each cell
- unsigned int max_n_contributions_per_cell = 1;
- for (typename CellToNormalsMap::const_iterator
- x = cell_to_normals_map.begin();
- x != cell_to_normals_map.end(); ++x)
- max_n_contributions_per_cell
- = std::max (max_n_contributions_per_cell,
- x->second.second);
-
- // verify that each cell can have only
- // contributed at most dim times, since
- // that is the maximum number of faces
- // that come together at a single place
- Assert (max_n_contributions_per_cell <= dim, ExcInternalError());
-
- switch (max_n_contributions_per_cell)
+ case 3:
{
- // first deal with the case that a
- // number of cells all have
- // registered that they have a
- // normal vector defined at the
- // location of a given vector dof,
- // and that each of them have
- // encountered this vector dof
- // exactly once while looping over
- // all their faces. as stated in
- // the documentation, this is the
- // case where we want to simply
- // average over all normal vectors
- case 1:
- {
+ const unsigned int& n_dofs = dof_handler.n_dofs ();
+ std::vector<double> dof_values (n_dofs);
+ std::vector<unsigned int> projected_dofs (n_dofs);
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ projected_dofs[dof] = 0;
+
+ for (typename hp::DoFHandler<dim>::active_cell_iterator cell = dof_handler.begin_active ();
+ cell != dof_handler.end (); ++cell)
+ if (cell->at_boundary ())
+ for (unsigned int face = 0; face < GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face (face)->boundary_indicator () == boundary_component)
+ {
+ // This is only
+ // implemented, if the
+ // FE is a Raviart-Thomas
+ // element. If the FE is
+ // a FESystem we cannot
+ // check this.
+ if (dynamic_cast<const FESystem<dim>*> (&cell->get_fe ()) == 0)
+ {
+ typedef FiniteElement<dim> FEL;
- // compute the average
- // normal vector from all
- // the ones that have the
- // same set of dofs. we
- // could add them up and
- // divide them by the
- // number of additions,
- // or simply normalize
- // them right away since
- // we want them to have
- // unit length anyway
- Tensor<1,dim> normal;
- for (typename CellToNormalsMap::const_iterator
- x = cell_to_normals_map.begin();
- x != cell_to_normals_map.end(); ++x)
- normal += x->second.first;
- normal /= normal.norm();
-
- // normalize again
- for (unsigned int d=0; d<dim; ++d)
- if (std::fabs(normal[d]) < 1e-13)
- normal[d] = 0;
- normal /= normal.norm();
-
- // then construct constraints
- // from this:
- const internal::VectorTools::VectorDoFTuple<dim> &
- dof_indices = same_dof_range[0]->first;
- internal::VectorTools::add_constraint (dof_indices, normal,
- constraints);
+ AssertThrow (dynamic_cast<const FE_RaviartThomas<dim>*> (&cell->get_fe ()) != 0,
+ typename FEL::ExcInterpolationNotImplemented ());
+ }
- break;
- }
+ fe_values.reinit (cell, face + cell->active_fe_index ()
+ * GeometryInfo<dim>::faces_per_cell);
+ const std::vector<Tensor<2, dim> >&
+ jacobians = fe_values.get_present_fe_values ().get_jacobians ();
- // this is the slightly
- // more complicated case
- // that a single cell has
- // contributed with exactly
- // DIM normal vectors to
- // the same set of vector
- // dofs. this is what
- // happens in a corner in
- // 2d and 3d (but not on an
- // edge in 3d, where we
- // have only 2, i.e. <DIM,
- // contributions. Here we
- // do not want to average
- // the normal
- // vectors. Since we have
- // DIM contributions, let's
- // assume (and verify) that
- // they are in fact all
- // linearly independent; in
- // that case, all vector
- // components are
- // constrained and we need
- // to set them to zero
- case dim:
- {
- // assert that indeed
- // only a single cell has
- // contributed
- Assert (cell_to_normals_map.size() == 1,
- ExcInternalError());
+ fe_face_values.reinit (cell, face);
+ internals::compute_face_projection_div_conforming (cell, face,
+ fe_face_values.get_present_fe_values (),
+ first_vector_component,
+ boundary_function,
+ jacobians, dof_values,
+ projected_dofs);
+ }
+
+ for (unsigned int dof = 0; dof < n_dofs; ++dof)
+ if ((projected_dofs[dof] != 0) && !(constraints.is_constrained (dof)))
+ {
+ constraints.add_line (dof);
+
+ if (std::abs (dof_values[dof]) > 1e-14)
+ constraints.set_inhomogeneity (dof, dof_values[dof]);
+ }
+
+ break;
+ }
+
+ default:
+ Assert (false, ExcNotImplemented ());
+ }
+ }
+
+
+ template <int dim, template <int, int> class DH, int spacedim>
+ void
+
+ compute_no_normal_flux_constraints (const DH<dim,spacedim> &dof_handler,
+ const unsigned int first_vector_component,
+ const std::set<unsigned char> &boundary_ids,
+ ConstraintMatrix &constraints,
+ const Mapping<dim, spacedim> &mapping)
+ {
+ Assert (dim > 1,
+ ExcMessage ("This function is not useful in 1d because it amounts "
+ "to imposing Dirichlet values on the vector-valued "
+ "quantity."));
+
+ std::vector<unsigned int> face_dofs;
+
+ // create FE and mapping
+ // collections for all elements in
+ // use by this DoFHandler
+ hp::FECollection<dim,spacedim> fe_collection (dof_handler.get_fe());
+ hp::MappingCollection<dim,spacedim> mapping_collection;
+ for (unsigned int i=0; i<fe_collection.size(); ++i)
+ mapping_collection.push_back (mapping);
+
+ // now also create a quadrature
+ // collection for the faces of a
+ // cell. fill it with a quadrature
+ // formula with the support points
+ // on faces for each FE
+ hp::QCollection<dim-1> face_quadrature_collection;
+ for (unsigned int i=0; i<fe_collection.size(); ++i)
+ {
+ const std::vector<Point<dim-1> > &
+ unit_support_points = fe_collection[i].get_unit_face_support_points();
+
+ Assert (unit_support_points.size() == fe_collection[i].dofs_per_face,
+ ExcInternalError());
- // check linear
- // independence by
- // computing the
- // determinant of the
- // matrix created from
- // all the normal
- // vectors. if they are
- // linearly independent,
- // then the determinant
- // is nonzero. if they
- // are orthogonal, then
- // the matrix is in fact
- // equal to 1 (since they
- // are all unit vectors);
- // make sure the
- // determinant is larger
- // than 1e-3 to avoid
- // cases where cells are
- // degenerate
+ face_quadrature_collection
+ .push_back (Quadrature<dim-1> (unit_support_points));
+ }
+
+ // now create the object with which
+ // we will generate the normal
+ // vectors
+ hp::FEFaceValues<dim,spacedim> x_fe_face_values (mapping_collection,
+ fe_collection,
+ face_quadrature_collection,
+ update_q_points);
+
+ // have a map that stores normal
+ // vectors for each vector-dof
+ // tuple we want to
+ // constrain. since we can get at
+ // the same vector dof tuple more
+ // than once (for example if it is
+ // located at a vertex that we
+ // visit from all adjacent cells),
+ // we will want to average later on
+ // the normal vectors computed on
+ // different cells as described in
+ // the documentation of this
+ // function. however, we can only
+ // average if the contributions
+ // came from different cells,
+ // whereas we want to constrain
+ // twice or more in case the
+ // contributions came from
+ // different faces of the same cell
+ // (i.e. constrain not just the
+ // *average normal direction* but
+ // *all normal directions* we
+ // find). consequently, we also
+ // have to store which cell a
+ // normal vector was computed on
+ typedef
+ std::multimap<internal::VectorDoFTuple<dim>,
+ std::pair<Tensor<1,dim>, typename DH<dim,spacedim>::active_cell_iterator> >
+ DoFToNormalsMap;
+
+ DoFToNormalsMap dof_to_normals_map;
+
+ // now loop over all cells and all faces
+ typename DH<dim,spacedim>::active_cell_iterator
+ cell = dof_handler.begin_active(),
+ endc = dof_handler.end();
+ for (; cell!=endc; ++cell)
+ if (!cell->is_artificial())
+ for (unsigned int face_no=0; face_no < GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
+ if (boundary_ids.find(cell->face(face_no)->boundary_indicator())
+ != boundary_ids.end())
{
- Tensor<2,dim> t;
+ const FiniteElement<dim>& fe = cell->get_fe ();
+ typename DH<dim,spacedim>::face_iterator face = cell->face(face_no);
+
+ // get the indices of the
+ // dofs on this cell...
+ face_dofs.resize (fe.dofs_per_face);
+ face->get_dof_indices (face_dofs, cell->active_fe_index());
- typename DoFToNormalsMap::const_iterator x = same_dof_range[0];
- for (unsigned int i=0; i<dim; ++i, ++x)
- for (unsigned int j=0; j<dim; ++j)
- t[i][j] = x->second.first[j];
+ x_fe_face_values.reinit (cell, face_no);
+ const FEFaceValues<dim> &fe_values = x_fe_face_values.get_present_fe_values();
+
+ // then identify which of
+ // them correspond to the
+ // selected set of vector
+ // components
+ for (unsigned int i=0; i<face_dofs.size(); ++i)
+ if (fe.face_system_to_component_index(i).first ==
+ first_vector_component)
+ {
+ // find corresponding other
+ // components of vector
+ internal::VectorDoFTuple<dim> vector_dofs;
+ vector_dofs.dof_indices[0] = face_dofs[i];
+
+ for (unsigned int k=0; k<fe.dofs_per_face; ++k)
+ if ((k != i)
+ &&
+ (face_quadrature_collection[cell->active_fe_index()].point(k) ==
+ face_quadrature_collection[cell->active_fe_index()].point(i))
+ &&
+ (fe.face_system_to_component_index(k).first >=
+ first_vector_component)
+ &&
+ (fe.face_system_to_component_index(k).first <
+ first_vector_component + dim))
+ vector_dofs.dof_indices[fe.face_system_to_component_index(k).first -
+ first_vector_component]
+ = face_dofs[k];
+
+ for (unsigned int d=0; d<dim; ++d)
+ Assert (vector_dofs.dof_indices[d] < dof_handler.n_dofs(),
+ ExcInternalError());
+
+ // we need the normal
+ // vector on this face. we
+ // know that it is a vector
+ // of length 1 but at least
+ // with higher order
+ // mappings it isn't always
+ // possible to guarantee
+ // that each component is
+ // exact up to zero
+ // tolerance. in
+ // particular, as shown in
+ // the deal.II/no_flux_06
+ // test, if we just take
+ // the normal vector as
+ // given by the fe_values
+ // object, we can get
+ // entries in the normal
+ // vectors of the unit cube
+ // that have entries up to
+ // several times 1e-14.
+ //
+ // the problem with this is
+ // that this later yields
+ // constraints that are
+ // circular (e.g., in the
+ // testcase, we get
+ // constraints of the form
+ //
+ // x22 = 2.93099e-14*x21 + 2.93099e-14*x23
+ // x21 = -2.93099e-14*x22 + 2.93099e-14*x21
+ //
+ // in both of these
+ // constraints, the small
+ // numbers should be zero
+ // and the constraints
+ // should simply be
+ // x22 = x21 = 0
+ //
+ // to achieve this, we
+ // utilize that we know
+ // that the normal vector
+ // has (or should have)
+ // length 1 and that we can
+ // simply set small
+ // elements to zero
+ // (without having to check
+ // that they are small
+ // *relative to something
+ // else*). we do this and
+ // then normalize the
+ // length of the vector
+ // back to one, just to be
+ // on the safe side
+ Point<dim> normal_vector
+ = (cell->face(face_no)->get_boundary()
+ .normal_vector (cell->face(face_no),
+ fe_values.quadrature_point(i)));
+ Assert (std::fabs(normal_vector.norm() - 1) < 1e-14,
+ ExcInternalError());
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::fabs(normal_vector[d]) < 1e-13)
+ normal_vector[d] = 0;
+ normal_vector /= normal_vector.norm();
+
+ // now enter the
+ // (dofs,(normal_vector,cell))
+ // entry into the map
+ dof_to_normals_map
+ .insert (std::make_pair (vector_dofs,
+ std::make_pair (normal_vector,
+ cell)));
+ }
+ }
- Assert (std::fabs(determinant (t)) > 1e-3,
- ExcMessage("Found a set of normal vectors that are nearly collinear."));
+ // Now do something with the
+ // collected information. To this
+ // end, loop through all sets of
+ // pairs (dofs,normal_vector) and
+ // identify which entries belong to
+ // the same set of dofs and then do
+ // as described in the
+ // documentation, i.e. either
+ // average the normal vector or
+ // don't for this particular set of
+ // dofs
+ typename DoFToNormalsMap::const_iterator
+ p = dof_to_normals_map.begin();
+
+ while (p != dof_to_normals_map.end())
+ {
+ // first find the range of entries in
+ // the multimap that corresponds to the
+ // same vector-dof tuple. as usual, we
+ // define the range half-open. the
+ // first entry of course is 'p'
+ typename DoFToNormalsMap::const_iterator same_dof_range[2]
+ = { p };
+ for (++p; p != dof_to_normals_map.end(); ++p)
+ if (p->first != same_dof_range[0]->first)
+ {
+ same_dof_range[1] = p;
+ break;
+ }
+ if (p == dof_to_normals_map.end())
+ same_dof_range[1] = dof_to_normals_map.end();
+
+ // now compute the reverse mapping: for
+ // each of the cells that contributed
+ // to the current set of vector dofs,
+ // add up the normal vectors. the
+ // values of the map are pairs of
+ // normal vectors and number of cells
+ // that have contributed
+ typedef
+ std::map
+ <typename DH<dim,spacedim>::active_cell_iterator,
+ std::pair<Tensor<1,dim>, unsigned int> >
+ CellToNormalsMap;
+
+ CellToNormalsMap cell_to_normals_map;
+ for (typename DoFToNormalsMap::const_iterator
+ q = same_dof_range[0];
+ q != same_dof_range[1]; ++q)
+ if (cell_to_normals_map.find (q->second.second)
+ == cell_to_normals_map.end())
+ cell_to_normals_map[q->second.second]
+ = std::make_pair (q->second.first, 1U);
+ else
+ {
+ const Tensor<1,dim> old_normal
+ = cell_to_normals_map[q->second.second].first;
+ const unsigned int old_count
+ = cell_to_normals_map[q->second.second].second;
+
+ Assert (old_count > 0, ExcInternalError());
+
+ // in the same entry,
+ // store again the now
+ // averaged normal vector
+ // and the new count
+ cell_to_normals_map[q->second.second]
+ = std::make_pair ((old_normal * old_count + q->second.first) / (old_count + 1),
+ old_count + 1);
}
- // so all components of
- // this vector dof are
- // constrained. enter
- // this into the
- // constraint matrix
- //
- // ignore dofs already
- // constrained
- for (unsigned int i=0; i<dim; ++i)
- if (!constraints.is_constrained (same_dof_range[0]
- ->first.dof_indices[i])
- &&
- constraints.can_store_line(
- same_dof_range[0]->first.dof_indices[i]))
- {
- constraints.add_line (same_dof_range[0]->first.dof_indices[i]);
- // no add_entries here
- }
+ Assert (cell_to_normals_map.size() >= 1, ExcInternalError());
+
+ // count the maximum number of
+ // contributions from each cell
+ unsigned int max_n_contributions_per_cell = 1;
+ for (typename CellToNormalsMap::const_iterator
+ x = cell_to_normals_map.begin();
+ x != cell_to_normals_map.end(); ++x)
+ max_n_contributions_per_cell
+ = std::max (max_n_contributions_per_cell,
+ x->second.second);
+
+ // verify that each cell can have only
+ // contributed at most dim times, since
+ // that is the maximum number of faces
+ // that come together at a single place
+ Assert (max_n_contributions_per_cell <= dim, ExcInternalError());
+
+ switch (max_n_contributions_per_cell)
+ {
+ // first deal with the case that a
+ // number of cells all have
+ // registered that they have a
+ // normal vector defined at the
+ // location of a given vector dof,
+ // and that each of them have
+ // encountered this vector dof
+ // exactly once while looping over
+ // all their faces. as stated in
+ // the documentation, this is the
+ // case where we want to simply
+ // average over all normal vectors
+ case 1:
+ {
- break;
- }
+ // compute the average
+ // normal vector from all
+ // the ones that have the
+ // same set of dofs. we
+ // could add them up and
+ // divide them by the
+ // number of additions,
+ // or simply normalize
+ // them right away since
+ // we want them to have
+ // unit length anyway
+ Tensor<1,dim> normal;
+ for (typename CellToNormalsMap::const_iterator
+ x = cell_to_normals_map.begin();
+ x != cell_to_normals_map.end(); ++x)
+ normal += x->second.first;
+ normal /= normal.norm();
+
+ // normalize again
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::fabs(normal[d]) < 1e-13)
+ normal[d] = 0;
+ normal /= normal.norm();
+
+ // then construct constraints
+ // from this:
+ const internal::VectorDoFTuple<dim> &
+ dof_indices = same_dof_range[0]->first;
+ internal::add_constraint (dof_indices, normal,
+ constraints);
+ break;
+ }
- // this is the case of an
- // edge contribution in 3d,
- // i.e. the vector is
- // constrained in two
- // directions but not the
- // third.
- default:
- {
- Assert (dim >= 3, ExcNotImplemented());
- Assert (max_n_contributions_per_cell == 2, ExcInternalError());
-
- // as described in the
- // documentation, let us
- // first collect what
- // each of the cells
- // contributed at the
- // current point. we use
- // a std::list instead of
- // a std::set (which
- // would be more natural)
- // because std::set
- // requires that the
- // stored elements are
- // comparable with
- // operator<
- typedef
- std::map<typename DH<dim,spacedim>::active_cell_iterator, std::list<Tensor<1,dim> > >
- CellContributions;
- CellContributions cell_contributions;
-
- for (typename DoFToNormalsMap::const_iterator
- q = same_dof_range[0];
- q != same_dof_range[1]; ++q)
- cell_contributions[q->second.second].push_back (q->second.first);
- Assert (cell_contributions.size() >= 1, ExcInternalError());
-
- // now for each cell that
- // has contributed
- // determine the number
- // of normal vectors it
- // has contributed. we
- // currently only
- // implement if this is
- // dim-1 for all cells
- // (if a single cell has
- // contributed dim, or if
- // all adjacent cells
- // have contributed 1
- // normal vector, this is
- // already handled above)
- //
- // for each contributing
- // cell compute the
- // tangential vector that
- // remains unconstrained
- std::list<Tensor<1,dim> > tangential_vectors;
- for (typename CellContributions::const_iterator
- contribution = cell_contributions.begin();
- contribution != cell_contributions.end();
- ++contribution)
+
+ // this is the slightly
+ // more complicated case
+ // that a single cell has
+ // contributed with exactly
+ // DIM normal vectors to
+ // the same set of vector
+ // dofs. this is what
+ // happens in a corner in
+ // 2d and 3d (but not on an
+ // edge in 3d, where we
+ // have only 2, i.e. <DIM,
+ // contributions. Here we
+ // do not want to average
+ // the normal
+ // vectors. Since we have
+ // DIM contributions, let's
+ // assume (and verify) that
+ // they are in fact all
+ // linearly independent; in
+ // that case, all vector
+ // components are
+ // constrained and we need
+ // to set them to zero
+ case dim:
+ {
+ // assert that indeed
+ // only a single cell has
+ // contributed
+ Assert (cell_to_normals_map.size() == 1,
+ ExcInternalError());
+
+ // check linear
+ // independence by
+ // computing the
+ // determinant of the
+ // matrix created from
+ // all the normal
+ // vectors. if they are
+ // linearly independent,
+ // then the determinant
+ // is nonzero. if they
+ // are orthogonal, then
+ // the matrix is in fact
+ // equal to 1 (since they
+ // are all unit vectors);
+ // make sure the
+ // determinant is larger
+ // than 1e-3 to avoid
+ // cases where cells are
+ // degenerate
{
- Assert (contribution->second.size() == dim-1, ExcNotImplemented());
+ Tensor<2,dim> t;
- Tensor<1,dim> normals[dim-1];
- {
- unsigned int index=0;
- for (typename std::list<Tensor<1,dim> >::const_iterator
- t = contribution->second.begin();
- t != contribution->second.end();
- ++t, ++index)
- normals[index] = *t;
- Assert (index == dim-1, ExcInternalError());
- }
+ typename DoFToNormalsMap::const_iterator x = same_dof_range[0];
+ for (unsigned int i=0; i<dim; ++i, ++x)
+ for (unsigned int j=0; j<dim; ++j)
+ t[i][j] = x->second.first[j];
+
+ Assert (std::fabs(determinant (t)) > 1e-3,
+ ExcMessage("Found a set of normal vectors that are nearly collinear."));
+ }
- // calculate the
- // tangent as the
- // outer product of
- // the normal
- // vectors. since
- // these vectors do
- // not need to be
- // orthogonal (think,
- // for example, the
- // case of the
- // deal.II/no_flux_07
- // test: a sheared
- // cube in 3d, with
- // Q2 elements, where
- // we have
- // constraints from
- // the two normal
- // vectors of two
- // faces of the
- // sheared cube that
- // are not
- // perpendicular to
- // each other), we
- // have to normalize
- // the outer product
- Tensor<1,dim> tangent;
- switch (dim)
+ // so all components of
+ // this vector dof are
+ // constrained. enter
+ // this into the
+ // constraint matrix
+ //
+ // ignore dofs already
+ // constrained
+ for (unsigned int i=0; i<dim; ++i)
+ if (!constraints.is_constrained (same_dof_range[0]
+ ->first.dof_indices[i])
+ &&
+ constraints.can_store_line(
+ same_dof_range[0]->first.dof_indices[i]))
{
- case 3:
- // take
- // cross
- // product
- // between
- // normals[0]
- // and
- // normals[1]. write
- // it in
- // the
- // current
- // form
- // (with
- // [dim-2])
- // to make
- // sure
- // that
- // compilers
- // don't
- // warn
- // about
- // out-of-bounds
- // accesses
- // -- the
- // warnings
- // are
- // bogus
- // since we
- // get here
- // only for
- // dim==3,
- // but at
- // least
- // one
- // isn't
- // quite
- // smart
- // enough
- // to
- // notice
- // this and
- // warns
- // when
- // compiling
- // the
- // function
- // in 2d
- cross_product (tangent, normals[0], normals[dim-2]);
- break;
- default:
- Assert (false, ExcNotImplemented());
+ constraints.add_line (same_dof_range[0]->first.dof_indices[i]);
+ // no add_entries here
}
- Assert (std::fabs (tangent.norm()) > 1e-12,
- ExcMessage("Two normal vectors from adjacent faces are almost "
- "parallel."));
- tangent /= tangent.norm();
+ break;
+ }
- tangential_vectors.push_back (tangent);
- }
- // go through the list of
- // tangents and make sure
- // that they all roughly
- // point in the same
- // direction as the first
- // one (i.e. have an
- // angle less than 90
- // degrees); if they
- // don't then flip their
- // sign
+ // this is the case of an
+ // edge contribution in 3d,
+ // i.e. the vector is
+ // constrained in two
+ // directions but not the
+ // third.
+ default:
{
- const Tensor<1,dim> first_tangent = tangential_vectors.front();
- typename std::list<Tensor<1,dim> >::iterator
- t = tangential_vectors.begin();
- ++t;
- for (; t != tangential_vectors.end(); ++t)
- if (*t * first_tangent < 0)
- *t *= -1;
- }
+ Assert (dim >= 3, ExcNotImplemented());
+ Assert (max_n_contributions_per_cell == 2, ExcInternalError());
+
+ // as described in the
+ // documentation, let us
+ // first collect what
+ // each of the cells
+ // contributed at the
+ // current point. we use
+ // a std::list instead of
+ // a std::set (which
+ // would be more natural)
+ // because std::set
+ // requires that the
+ // stored elements are
+ // comparable with
+ // operator<
+ typedef
+ std::map<typename DH<dim,spacedim>::active_cell_iterator, std::list<Tensor<1,dim> > >
+ CellContributions;
+ CellContributions cell_contributions;
+
+ for (typename DoFToNormalsMap::const_iterator
+ q = same_dof_range[0];
+ q != same_dof_range[1]; ++q)
+ cell_contributions[q->second.second].push_back (q->second.first);
+ Assert (cell_contributions.size() >= 1, ExcInternalError());
+
+ // now for each cell that
+ // has contributed
+ // determine the number
+ // of normal vectors it
+ // has contributed. we
+ // currently only
+ // implement if this is
+ // dim-1 for all cells
+ // (if a single cell has
+ // contributed dim, or if
+ // all adjacent cells
+ // have contributed 1
+ // normal vector, this is
+ // already handled above)
+ //
+ // for each contributing
+ // cell compute the
+ // tangential vector that
+ // remains unconstrained
+ std::list<Tensor<1,dim> > tangential_vectors;
+ for (typename CellContributions::const_iterator
+ contribution = cell_contributions.begin();
+ contribution != cell_contributions.end();
+ ++contribution)
+ {
+ Assert (contribution->second.size() == dim-1, ExcNotImplemented());
- // now compute the
- // average tangent and
- // normalize it
- Tensor<1,dim> average_tangent;
- for (typename std::list<Tensor<1,dim> >::const_iterator
- t = tangential_vectors.begin();
- t != tangential_vectors.end();
- ++t)
- average_tangent += *t;
- average_tangent /= average_tangent.norm();
-
- // from the tangent
- // vector we now need to
- // again reconstruct dim-1
- // normal directions in
- // which the vector field
- // is to be constrained
- Tensor<1,dim> constraining_normals[dim-1];
- internal::VectorTools::
- compute_orthonormal_vectors<dim> (average_tangent,
- constraining_normals);
- // normalize again
- for (unsigned int e=0; e<dim-1; ++e)
+ Tensor<1,dim> normals[dim-1];
+ {
+ unsigned int index=0;
+ for (typename std::list<Tensor<1,dim> >::const_iterator
+ t = contribution->second.begin();
+ t != contribution->second.end();
+ ++t, ++index)
+ normals[index] = *t;
+ Assert (index == dim-1, ExcInternalError());
+ }
+
+ // calculate the
+ // tangent as the
+ // outer product of
+ // the normal
+ // vectors. since
+ // these vectors do
+ // not need to be
+ // orthogonal (think,
+ // for example, the
+ // case of the
+ // deal.II/no_flux_07
+ // test: a sheared
+ // cube in 3d, with
+ // Q2 elements, where
+ // we have
+ // constraints from
+ // the two normal
+ // vectors of two
+ // faces of the
+ // sheared cube that
+ // are not
+ // perpendicular to
+ // each other), we
+ // have to normalize
+ // the outer product
+ Tensor<1,dim> tangent;
+ switch (dim)
+ {
+ case 3:
+ // take
+ // cross
+ // product
+ // between
+ // normals[0]
+ // and
+ // normals[1]. write
+ // it in
+ // the
+ // current
+ // form
+ // (with
+ // [dim-2])
+ // to make
+ // sure
+ // that
+ // compilers
+ // don't
+ // warn
+ // about
+ // out-of-bounds
+ // accesses
+ // -- the
+ // warnings
+ // are
+ // bogus
+ // since we
+ // get here
+ // only for
+ // dim==3,
+ // but at
+ // least
+ // one
+ // isn't
+ // quite
+ // smart
+ // enough
+ // to
+ // notice
+ // this and
+ // warns
+ // when
+ // compiling
+ // the
+ // function
+ // in 2d
+ cross_product (tangent, normals[0], normals[dim-2]);
+ break;
+ default:
+ Assert (false, ExcNotImplemented());
+ }
+
+ Assert (std::fabs (tangent.norm()) > 1e-12,
+ ExcMessage("Two normal vectors from adjacent faces are almost "
+ "parallel."));
+ tangent /= tangent.norm();
+
+ tangential_vectors.push_back (tangent);
+ }
+
+ // go through the list of
+ // tangents and make sure
+ // that they all roughly
+ // point in the same
+ // direction as the first
+ // one (i.e. have an
+ // angle less than 90
+ // degrees); if they
+ // don't then flip their
+ // sign
{
- for (unsigned int d=0; d<dim; ++d)
- if (std::fabs(constraining_normals[e][d]) < 1e-13)
- constraining_normals[e][d] = 0;
- constraining_normals[e] /= constraining_normals[e].norm();
+ const Tensor<1,dim> first_tangent = tangential_vectors.front();
+ typename std::list<Tensor<1,dim> >::iterator
+ t = tangential_vectors.begin();
+ ++t;
+ for (; t != tangential_vectors.end(); ++t)
+ if (*t * first_tangent < 0)
+ *t *= -1;
}
- // now all that is left
- // is that we add the
- // constraints for these
- // dim-1 vectors
- const internal::VectorTools::VectorDoFTuple<dim> &
+ // now compute the
+ // average tangent and
+ // normalize it
+ Tensor<1,dim> average_tangent;
+ for (typename std::list<Tensor<1,dim> >::const_iterator
+ t = tangential_vectors.begin();
+ t != tangential_vectors.end();
+ ++t)
+ average_tangent += *t;
+ average_tangent /= average_tangent.norm();
+
+ // from the tangent
+ // vector we now need to
+ // again reconstruct dim-1
+ // normal directions in
+ // which the vector field
+ // is to be constrained
+ Tensor<1,dim> constraining_normals[dim-1];
+ internal::
+ compute_orthonormal_vectors<dim> (average_tangent,
+ constraining_normals);
+ // normalize again
+ for (unsigned int e=0; e<dim-1; ++e)
+ {
+ for (unsigned int d=0; d<dim; ++d)
+ if (std::fabs(constraining_normals[e][d]) < 1e-13)
+ constraining_normals[e][d] = 0;
+ constraining_normals[e] /= constraining_normals[e].norm();
+ }
+
+ // now all that is left
+ // is that we add the
+ // constraints for these
+ // dim-1 vectors
+ const internal::VectorDoFTuple<dim> &
dof_indices = same_dof_range[0]->first;
- for (unsigned int c=0; c<dim-1; ++c)
- internal::VectorTools::add_constraint (dof_indices,
- constraining_normals[c],
- constraints);
+ for (unsigned int c=0; c<dim-1; ++c)
+ internal::add_constraint (dof_indices,
+ constraining_normals[c],
+ constraints);
+ }
}
- }
- }
-}
+ }
+ }
-namespace internal
-{
- namespace VectorTools
+ namespace internal
{
template <int dim, class InVector, class OutVector, class DH, int spacedim>
static
void
do_integrate_difference (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
- const DH &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const dealii::hp::QCollection<dim> &q,
- const dealii::VectorTools::NormType &norm,
- const Function<spacedim> *weight,
- const double exponent_1)
+ const DH &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const dealii::hp::QCollection<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const double exponent_1)
{
- // we mark the "exponent" parameter
- // to this function "const" since
- // it is strictly incoming, but we
- // need to set it to something
- // different later on, if
- // necessary, so have a read-write
- // version of it:
+ // we mark the "exponent" parameter
+ // to this function "const" since
+ // it is strictly incoming, but we
+ // need to set it to something
+ // different later on, if
+ // necessary, so have a read-write
+ // version of it:
double exponent = exponent_1;
const unsigned int n_components = dof.get_fe().n_components();
const bool fe_is_system = (n_components != 1);
if (weight!=0)
- {
- Assert ((weight->n_components==1) || (weight->n_components==n_components),
- ExcDimensionMismatch(weight->n_components, n_components));
- }
+ {
+ Assert ((weight->n_components==1) || (weight->n_components==n_components),
+ ExcDimensionMismatch(weight->n_components, n_components));
+ }
difference.reinit (dof.get_tria().n_active_cells());
switch (norm)
- {
- case dealii::VectorTools::L2_norm:
- case dealii::VectorTools::H1_seminorm:
- case dealii::VectorTools::H1_norm:
- exponent = 2.;
- break;
- case dealii::VectorTools::L1_norm:
- exponent = 1.;
- break;
- default:
- break;
- }
+ {
+ case L2_norm:
+ case H1_seminorm:
+ case H1_norm:
+ exponent = 2.;
+ break;
+ case L1_norm:
+ exponent = 1.;
+ break;
+ default:
+ break;
+ }
UpdateFlags update_flags = UpdateFlags (update_quadrature_points |
- update_JxW_values);
+ update_JxW_values);
switch (norm)
- {
- case dealii::VectorTools::H1_seminorm:
- case dealii::VectorTools::W1p_seminorm:
- case dealii::VectorTools::W1infty_seminorm:
- update_flags |= UpdateFlags (update_gradients);
+ {
+ case H1_seminorm:
+ case W1p_seminorm:
+ case W1infty_seminorm:
+ update_flags |= UpdateFlags (update_gradients);
if(spacedim == dim+1) update_flags |= UpdateFlags (update_normal_vectors);
- break;
- case dealii::VectorTools::H1_norm:
- case dealii::VectorTools::W1p_norm:
- case dealii::VectorTools::W1infty_norm:
- update_flags |= UpdateFlags (update_gradients);
+ break;
+ case H1_norm:
+ case W1p_norm:
+ case W1infty_norm:
+ update_flags |= UpdateFlags (update_gradients);
if(spacedim == dim+1) update_flags |= UpdateFlags (update_normal_vectors);
- // no break!
- default:
- update_flags |= UpdateFlags (update_values);
- break;
- }
+ // no break!
+ default:
+ update_flags |= UpdateFlags (update_values);
+ break;
+ }
dealii::hp::FECollection<dim,spacedim> fe_collection (dof.get_fe());
dealii::hp::FEValues<dim,spacedim> x_fe_values(mapping, fe_collection, q, update_flags);
const unsigned int max_n_q_points = q.max_n_quadrature_points ();
std::vector< dealii::Vector<double> >
- function_values (max_n_q_points, dealii::Vector<double>(n_components));
+ function_values (max_n_q_points, dealii::Vector<double>(n_components));
std::vector<std::vector<Tensor<1,spacedim> > >
- function_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
+ function_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
std::vector<double>
- weight_values (max_n_q_points);
+ weight_values (max_n_q_points);
std::vector<dealii::Vector<double> >
- weight_vectors (max_n_q_points, dealii::Vector<double>(n_components));
+ weight_vectors (max_n_q_points, dealii::Vector<double>(n_components));
std::vector<dealii::Vector<double> >
- psi_values (max_n_q_points, dealii::Vector<double>(n_components));
+ psi_values (max_n_q_points, dealii::Vector<double>(n_components));
std::vector<std::vector<Tensor<1,spacedim> > >
- psi_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
+ psi_grads (max_n_q_points, std::vector<Tensor<1,spacedim> >(n_components));
std::vector<double>
- psi_scalar (max_n_q_points);
+ psi_scalar (max_n_q_points);
- // tmp vector when we use the
- // Function<spacedim> functions for
- // scalar functions
+ // tmp vector when we use the
+ // Function<spacedim> functions for
+ // scalar functions
std::vector<double> tmp_values (max_n_q_points);
std::vector<Tensor<1,spacedim> > tmp_gradients (max_n_q_points);
- // loop over all cells
+ // loop over all cells
typename DH::active_cell_iterator cell = dof.begin_active(),
- endc = dof.end();
+ endc = dof.end();
for (unsigned int index=0; cell != endc; ++cell, ++index)
if (cell->is_locally_owned())
{
switch (norm)
{
- case dealii::VectorTools::mean:
+ case mean:
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
// Compute values in
// quadrature points
fe_values.get_JxW_values().begin(),
0.0);
break;
- case dealii::VectorTools::Lp_norm:
- case dealii::VectorTools::L1_norm:
- case dealii::VectorTools::W1p_norm:
+ case Lp_norm:
+ case L1_norm:
+ case W1p_norm:
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
// Compute values in
// quadrature points
if (!(update_flags & update_gradients))
diff = std::pow(diff, 1./exponent);
break;
- case dealii::VectorTools::L2_norm:
- case dealii::VectorTools::H1_norm:
+ case L2_norm:
+ case H1_norm:
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
// Compute values in
// quadrature points
// Compute the root only,
// if no derivative
// values are added later
- if (norm == dealii::VectorTools::L2_norm)
+ if (norm == L2_norm)
diff=std::sqrt(diff);
break;
- case dealii::VectorTools::Linfty_norm:
- case dealii::VectorTools::W1infty_norm:
+ case Linfty_norm:
+ case W1infty_norm:
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
for (unsigned int k=0; k<n_components; ++k)
for (unsigned int q=0; q<n_q_points; ++q)
// Maximum on one cell
diff = *std::max_element (psi_scalar.begin(), psi_scalar.end());
break;
- case dealii::VectorTools::H1_seminorm:
- case dealii::VectorTools::W1p_seminorm:
- case dealii::VectorTools::W1infty_seminorm:
+ case H1_seminorm:
+ case W1p_seminorm:
+ case W1infty_seminorm:
break;
default:
Assert (false, ExcNotImplemented());
switch (norm)
{
- case dealii::VectorTools::W1p_seminorm:
- case dealii::VectorTools::W1p_norm:
+ case W1p_seminorm:
+ case W1p_norm:
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
for (unsigned int k=0; k<n_components; ++k)
for (unsigned int q=0; q<n_q_points; ++q)
0.0);
diff = std::pow(diff, 1./exponent);
break;
- case dealii::VectorTools::H1_seminorm:
- case dealii::VectorTools::H1_norm:
+ case H1_seminorm:
+ case H1_norm:
// take square of integrand
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
for (unsigned int k=0; k<n_components; ++k)
0.0);
diff = std::sqrt(diff);
break;
- case dealii::VectorTools::W1infty_seminorm:
- case dealii::VectorTools::W1infty_norm:
+ case W1infty_seminorm:
+ case W1infty_norm:
Assert(false, ExcNotImplemented());
std::fill_n (psi_scalar.begin(), n_q_points, 0.0);
for (unsigned int k=0; k<n_components; ++k)
difference(index) = 0;
}
- } //namespace VectorTools
-} // namespace internal
+ } // namespace internal
-template <int dim, class InVector, class OutVector, int spacedim>
-void
-VectorTools::integrate_difference (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const Quadrature<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight,
- const double exponent)
-{
- internal::VectorTools
- ::do_integrate_difference (hp::MappingCollection<dim,spacedim>(mapping),
- dof, fe_function, exact_solution,
- difference, hp::QCollection<dim>(q),
- norm, weight, exponent);
-}
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ integrate_difference (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const Quadrature<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const double exponent)
+ {
+ internal
+ ::do_integrate_difference (hp::MappingCollection<dim,spacedim>(mapping),
+ dof, fe_function, exact_solution,
+ difference, hp::QCollection<dim>(q),
+ norm, weight, exponent);
+ }
-template <int dim, class InVector, class OutVector, int spacedim>
-void
-VectorTools::integrate_difference (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const Quadrature<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight,
- const double exponent)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- internal::VectorTools
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ integrate_difference (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const Quadrature<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const double exponent)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ internal
::do_integrate_difference(hp::StaticMappingQ1<dim,spacedim>::mapping_collection,
- dof, fe_function, exact_solution,
- difference, hp::QCollection<dim>(q),
- norm, weight, exponent);
-}
+ dof, fe_function, exact_solution,
+ difference, hp::QCollection<dim>(q),
+ norm, weight, exponent);
+ }
-template <int dim, class InVector, class OutVector, int spacedim>
-void
-VectorTools::integrate_difference (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
- const dealii::hp::DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const dealii::hp::QCollection<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight,
- const double exponent)
-{
- internal::VectorTools
- ::do_integrate_difference (hp::MappingCollection<dim,spacedim>(mapping),
- dof, fe_function, exact_solution,
- difference, q,
- norm, weight, exponent);
-}
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ integrate_difference (const dealii::hp::MappingCollection<dim,spacedim> &mapping,
+ const dealii::hp::DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const dealii::hp::QCollection<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const double exponent)
+ {
+ internal
+ ::do_integrate_difference (hp::MappingCollection<dim,spacedim>(mapping),
+ dof, fe_function, exact_solution,
+ difference, q,
+ norm, weight, exponent);
+ }
-template <int dim, class InVector, class OutVector, int spacedim>
-void
-VectorTools::integrate_difference (const dealii::hp::DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_solution,
- OutVector &difference,
- const dealii::hp::QCollection<dim> &q,
- const NormType &norm,
- const Function<spacedim> *weight,
- const double exponent)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- internal::VectorTools
- ::do_integrate_difference(hp::StaticMappingQ1<dim>::mapping_collection,
- dof, fe_function, exact_solution,
- difference, q,
- norm, weight, exponent);
-}
+ template <int dim, class InVector, class OutVector, int spacedim>
+ void
+ integrate_difference (const dealii::hp::DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_solution,
+ OutVector &difference,
+ const dealii::hp::QCollection<dim> &q,
+ const NormType &norm,
+ const Function<spacedim> *weight,
+ const double exponent)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ internal
+ ::do_integrate_difference(hp::StaticMappingQ1<dim>::mapping_collection,
+ dof, fe_function, exact_solution,
+ difference, q,
+ norm, weight, exponent);
+ }
-template <int dim, class InVector, int spacedim>
-void
-VectorTools::point_difference (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_function,
- Vector<double> &difference,
- const Point<spacedim> &point)
-{
- point_difference(StaticMappingQ1<dim>::mapping,
- dof,
- fe_function,
- exact_function,
- difference,
- point);
-}
+ template <int dim, class InVector, int spacedim>
+ void
+ point_difference (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_function,
+ Vector<double> &difference,
+ const Point<spacedim> &point)
+ {
+ point_difference(StaticMappingQ1<dim>::mapping,
+ dof,
+ fe_function,
+ exact_function,
+ difference,
+ point);
+ }
-template <int dim, class InVector, int spacedim>
-void
-VectorTools::point_difference (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Function<spacedim> &exact_function,
- Vector<double> &difference,
- const Point<spacedim> &point)
-{
- const FiniteElement<dim>& fe = dof.get_fe();
+ template <int dim, class InVector, int spacedim>
+ void
+ point_difference (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Function<spacedim> &exact_function,
+ Vector<double> &difference,
+ const Point<spacedim> &point)
+ {
+ const FiniteElement<dim>& fe = dof.get_fe();
- Assert(difference.size() == fe.n_components(),
- ExcDimensionMismatch(difference.size(), fe.n_components()));
+ Assert(difference.size() == fe.n_components(),
+ ExcDimensionMismatch(difference.size(), fe.n_components()));
- // first find the cell in which this point
- // is, initialize a quadrature rule with
- // it, and then a FEValues object
- const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
- cell_point = GridTools::find_active_cell_around_point (mapping, dof, point);
+ // first find the cell in which this point
+ // is, initialize a quadrature rule with
+ // it, and then a FEValues object
+ const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ cell_point = GridTools::find_active_cell_around_point (mapping, dof, point);
- Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
- ExcInternalError());
+ Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
+ ExcInternalError());
- const Quadrature<dim>
- quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
- FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
- fe_values.reinit(cell_point.first);
+ const Quadrature<dim>
+ quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
+ FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
+ fe_values.reinit(cell_point.first);
- // then use this to get at the values of
- // the given fe_function at this point
- std::vector<Vector<double> > u_value(1, Vector<double> (fe.n_components()));
- fe_values.get_function_values(fe_function, u_value);
+ // then use this to get at the values of
+ // the given fe_function at this point
+ std::vector<Vector<double> > u_value(1, Vector<double> (fe.n_components()));
+ fe_values.get_function_values(fe_function, u_value);
- if (fe.n_components() == 1)
- difference(0) = exact_function.value(point);
- else
- exact_function.vector_value(point, difference);
+ if (fe.n_components() == 1)
+ difference(0) = exact_function.value(point);
+ else
+ exact_function.vector_value(point, difference);
- for (unsigned int i=0; i<difference.size(); ++i)
- difference(i) -= u_value[0](i);
-}
+ for (unsigned int i=0; i<difference.size(); ++i)
+ difference(i) -= u_value[0](i);
+ }
-template <int dim, class InVector, int spacedim>
-void
-VectorTools::point_value (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point,
- Vector<double> &value)
-{
+ template <int dim, class InVector, int spacedim>
+ void
+ point_value (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point,
+ Vector<double> &value)
+ {
- point_value (StaticMappingQ1<dim,spacedim>::mapping,
- dof,
- fe_function,
- point,
- value);
-}
+ point_value (StaticMappingQ1<dim,spacedim>::mapping,
+ dof,
+ fe_function,
+ point,
+ value);
+ }
-template <int dim, class InVector, int spacedim>
-double
-VectorTools::point_value (const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point)
-{
- return point_value (StaticMappingQ1<dim,spacedim>::mapping,
- dof,
- fe_function,
- point);
-}
+ template <int dim, class InVector, int spacedim>
+ double
+ point_value (const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point)
+ {
+ return point_value (StaticMappingQ1<dim,spacedim>::mapping,
+ dof,
+ fe_function,
+ point);
+ }
-template <int dim, class InVector, int spacedim>
-void
-VectorTools::point_value (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point,
- Vector<double> &value)
-{
- const FiniteElement<dim>& fe = dof.get_fe();
+ template <int dim, class InVector, int spacedim>
+ void
+ point_value (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point,
+ Vector<double> &value)
+ {
+ const FiniteElement<dim>& fe = dof.get_fe();
- Assert(value.size() == fe.n_components(),
- ExcDimensionMismatch(value.size(), fe.n_components()));
+ Assert(value.size() == fe.n_components(),
+ ExcDimensionMismatch(value.size(), fe.n_components()));
- // first find the cell in which this point
- // is, initialize a quadrature rule with
- // it, and then a FEValues object
- const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
- cell_point
- = GridTools::find_active_cell_around_point (mapping, dof, point);
+ // first find the cell in which this point
+ // is, initialize a quadrature rule with
+ // it, and then a FEValues object
+ const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ cell_point
+ = GridTools::find_active_cell_around_point (mapping, dof, point);
- Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
- ExcInternalError());
+ Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
+ ExcInternalError());
- const Quadrature<dim>
- quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
+ const Quadrature<dim>
+ quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
- FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
- fe_values.reinit(cell_point.first);
+ FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
+ fe_values.reinit(cell_point.first);
- // then use this to get at the values of
- // the given fe_function at this point
- std::vector<Vector<double> > u_value(1, Vector<double> (fe.n_components()));
- fe_values.get_function_values(fe_function, u_value);
+ // then use this to get at the values of
+ // the given fe_function at this point
+ std::vector<Vector<double> > u_value(1, Vector<double> (fe.n_components()));
+ fe_values.get_function_values(fe_function, u_value);
- value = u_value[0];
-}
+ value = u_value[0];
+ }
-template <int dim, class InVector, int spacedim>
-double
-VectorTools::point_value (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const InVector &fe_function,
- const Point<spacedim> &point)
-{
- const FiniteElement<dim>& fe = dof.get_fe();
+ template <int dim, class InVector, int spacedim>
+ double
+ point_value (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const InVector &fe_function,
+ const Point<spacedim> &point)
+ {
+ const FiniteElement<dim>& fe = dof.get_fe();
- Assert(fe.n_components() == 1,
- ExcMessage ("Finite element is not scalar as is necessary for this function"));
+ Assert(fe.n_components() == 1,
+ ExcMessage ("Finite element is not scalar as is necessary for this function"));
- // first find the cell in which this point
- // is, initialize a quadrature rule with
- // it, and then a FEValues object
- const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
- cell_point = GridTools::find_active_cell_around_point (mapping, dof, point);
+ // first find the cell in which this point
+ // is, initialize a quadrature rule with
+ // it, and then a FEValues object
+ const std::pair<typename DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ cell_point = GridTools::find_active_cell_around_point (mapping, dof, point);
- Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
- ExcInternalError());
+ Assert(GeometryInfo<dim>::distance_to_unit_cell(cell_point.second) < 1e-10,
+ ExcInternalError());
- const Quadrature<dim>
- quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
- FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
- fe_values.reinit(cell_point.first);
+ const Quadrature<dim>
+ quadrature (GeometryInfo<dim>::project_to_unit_cell(cell_point.second));
+ FEValues<dim> fe_values(mapping, fe, quadrature, update_values);
+ fe_values.reinit(cell_point.first);
- // then use this to get at the values of
- // the given fe_function at this point
- std::vector<double> u_value(1);
- fe_values.get_function_values(fe_function, u_value);
+ // then use this to get at the values of
+ // the given fe_function at this point
+ std::vector<double> u_value(1);
+ fe_values.get_function_values(fe_function, u_value);
- return u_value[0];
-}
+ return u_value[0];
+ }
-template <int dim, class InVector, int spacedim>
-double
-VectorTools::compute_mean_value (const Mapping<dim, spacedim> &mapping,
- const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &quadrature,
- const InVector &v,
- const unsigned int component)
-{
- Assert (v.size() == dof.n_dofs(),
- ExcDimensionMismatch (v.size(), dof.n_dofs()));
- Assert (component < dof.get_fe().n_components(),
- ExcIndexRange(component, 0, dof.get_fe().n_components()));
-
- FEValues<dim,spacedim> fe(mapping, dof.get_fe(), quadrature,
- UpdateFlags(update_JxW_values
- | update_values));
-
- typename DoFHandler<dim,spacedim>::active_cell_iterator cell;
- std::vector<Vector<double> > values(quadrature.size(),
- Vector<double> (dof.get_fe().n_components()));
-
- double mean = 0.;
- double area = 0.;
- // Compute mean value
- for (cell = dof.begin_active(); cell != dof.end(); ++cell)
- if (cell->is_locally_owned())
- {
- fe.reinit (cell);
- fe.get_function_values(v, values);
- for (unsigned int k=0; k< quadrature.size(); ++k)
- {
- mean += fe.JxW(k) * values[k](component);
- area += fe.JxW(k);
- }
- }
+ template <int dim, class InVector, int spacedim>
+ double
+ compute_mean_value (const Mapping<dim, spacedim> &mapping,
+ const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &quadrature,
+ const InVector &v,
+ const unsigned int component)
+ {
+ Assert (v.size() == dof.n_dofs(),
+ ExcDimensionMismatch (v.size(), dof.n_dofs()));
+ Assert (component < dof.get_fe().n_components(),
+ ExcIndexRange(component, 0, dof.get_fe().n_components()));
+
+ FEValues<dim,spacedim> fe(mapping, dof.get_fe(), quadrature,
+ UpdateFlags(update_JxW_values
+ | update_values));
+
+ typename DoFHandler<dim,spacedim>::active_cell_iterator cell;
+ std::vector<Vector<double> > values(quadrature.size(),
+ Vector<double> (dof.get_fe().n_components()));
+
+ double mean = 0.;
+ double area = 0.;
+ // Compute mean value
+ for (cell = dof.begin_active(); cell != dof.end(); ++cell)
+ if (cell->is_locally_owned())
+ {
+ fe.reinit (cell);
+ fe.get_function_values(v, values);
+ for (unsigned int k=0; k< quadrature.size(); ++k)
+ {
+ mean += fe.JxW(k) * values[k](component);
+ area += fe.JxW(k);
+ }
+ }
#if DEAL_II_USE_P4EST
- // if this was a distributed
- // DoFHandler, we need to do the
- // reduction over the entire domain
- if (const parallel::distributed::Triangulation<dim,spacedim> *
- p_d_triangulation
- = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim> *>(&dof.get_tria()))
- {
- double my_values[2] = { mean, area };
- double global_values[2];
+ // if this was a distributed
+ // DoFHandler, we need to do the
+ // reduction over the entire domain
+ if (const parallel::distributed::Triangulation<dim,spacedim> *
+ p_d_triangulation
+ = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim> *>(&dof.get_tria()))
+ {
+ double my_values[2] = { mean, area };
+ double global_values[2];
- MPI_Allreduce (&my_values, &global_values, 2, MPI_DOUBLE,
- MPI_SUM,
- p_d_triangulation->get_communicator());
+ MPI_Allreduce (&my_values, &global_values, 2, MPI_DOUBLE,
+ MPI_SUM,
+ p_d_triangulation->get_communicator());
- mean = global_values[0];
- area = global_values[1];
- }
+ mean = global_values[0];
+ area = global_values[1];
+ }
#endif
- return (mean/area);
-}
+ return (mean/area);
+ }
-template <int dim, class InVector, int spacedim>
-double
-VectorTools::compute_mean_value (const DoFHandler<dim,spacedim> &dof,
- const Quadrature<dim> &quadrature,
- const InVector &v,
- const unsigned int component)
-{
- Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
- return compute_mean_value(StaticMappingQ1<dim,spacedim>::mapping, dof, quadrature, v, component);
+ template <int dim, class InVector, int spacedim>
+ double
+ compute_mean_value (const DoFHandler<dim,spacedim> &dof,
+ const Quadrature<dim> &quadrature,
+ const InVector &v,
+ const unsigned int component)
+ {
+ Assert (DEAL_II_COMPAT_MAPPING, ExcCompatibility("mapping"));
+ return compute_mean_value(StaticMappingQ1<dim,spacedim>::mapping, dof, quadrature, v, component);
+ }
}
DEAL_II_NAMESPACE_CLOSE
DEAL_II_NAMESPACE_OPEN
+namespace GridTools
+{
+
// This anonymous namespace contains utility functions to extract the
// triangulation from any container such as DoFHandler, MGDoFHandler,
// and the like
-namespace
-{
- template<int dim, int spacedim>
- const Triangulation<dim, spacedim> &
- get_tria(const Triangulation<dim, spacedim> &tria)
+ namespace
{
- return tria;
- }
+ template<int dim, int spacedim>
+ const Triangulation<dim, spacedim> &
+ get_tria(const Triangulation<dim, spacedim> &tria)
+ {
+ return tria;
+ }
- template<int dim, template<int, int> class Container, int spacedim>
- const Triangulation<dim,spacedim> &
- get_tria(const Container<dim,spacedim> &container)
- {
- return container.get_tria();
- }
+ template<int dim, template<int, int> class Container, int spacedim>
+ const Triangulation<dim,spacedim> &
+ get_tria(const Container<dim,spacedim> &container)
+ {
+ return container.get_tria();
+ }
- template<int dim, int spacedim>
- Triangulation<dim, spacedim> &
- get_tria(Triangulation<dim, spacedim> &tria)
- {
- return tria;
- }
+ template<int dim, int spacedim>
+ Triangulation<dim, spacedim> &
+ get_tria(Triangulation<dim, spacedim> &tria)
+ {
+ return tria;
+ }
- template<int dim, template<int, int> class Container, int spacedim>
- const Triangulation<dim,spacedim> &
- get_tria(Container<dim,spacedim> &container)
- {
- return container.get_tria();
+ template<int dim, template<int, int> class Container, int spacedim>
+ const Triangulation<dim,spacedim> &
+ get_tria(Container<dim,spacedim> &container)
+ {
+ return container.get_tria();
+ }
}
-}
-template <int dim, int spacedim>
-double
-GridTools::diameter (const Triangulation<dim, spacedim> &tria)
-{
- // we can't deal with distributed meshes
- // since we don't have all vertices
- // locally. there is one exception,
- // however: if the mesh has never been
- // refined. the way to test this is not to
- // ask tria.n_levels()==1, since this is
- // something that can happen on one
- // processor without being true on
- // all. however, we can ask for the global
- // number of active cells and use that
+ template <int dim, int spacedim>
+ double
+ diameter (const Triangulation<dim, spacedim> &tria)
+ {
+ // we can't deal with distributed meshes
+ // since we don't have all vertices
+ // locally. there is one exception,
+ // however: if the mesh has never been
+ // refined. the way to test this is not to
+ // ask tria.n_levels()==1, since this is
+ // something that can happen on one
+ // processor without being true on
+ // all. however, we can ask for the global
+ // number of active cells and use that
#ifdef DEAL_II_USE_P4EST
- if (const parallel::distributed::Triangulation<dim,spacedim> *p_tria
- = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&tria))
- Assert (p_tria->n_global_active_cells() == tria.n_cells(0),
- ExcNotImplemented());
+ if (const parallel::distributed::Triangulation<dim,spacedim> *p_tria
+ = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&tria))
+ Assert (p_tria->n_global_active_cells() == tria.n_cells(0),
+ ExcNotImplemented());
#endif
- // the algorithm used simply
- // traverses all cells and picks
- // out the boundary vertices. it
- // may or may not be faster to
- // simply get all vectors, don't
- // mark boundary vertices, and
- // compute the distances thereof,
- // but at least as the mesh is
- // refined, it seems better to
- // first mark boundary nodes, as
- // marking is O(N) in the number of
- // cells/vertices, while computing
- // the maximal distance is O(N*N)
- const std::vector<Point<spacedim> > &vertices = tria.get_vertices ();
- std::vector<bool> boundary_vertices (vertices.size(), false);
-
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = tria.begin_active();
- const typename Triangulation<dim,spacedim>::active_cell_iterator
- endc = tria.end();
- for (; cell!=endc; ++cell)
- for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
- if (cell->face(face)->at_boundary ())
- for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
- boundary_vertices[cell->face(face)->vertex_index(i)] = true;
-
- // now traverse the list of
- // boundary vertices and check
- // distances. since distances are
- // symmetric, we only have to check
- // one half
- double max_distance_sqr = 0;
- std::vector<bool>::const_iterator pi = boundary_vertices.begin();
- const unsigned int N = boundary_vertices.size();
- for (unsigned int i=0; i<N; ++i, ++pi)
- {
- std::vector<bool>::const_iterator pj = pi+1;
- for (unsigned int j=i+1; j<N; ++j, ++pj)
- if ((*pi==true) && (*pj==true) &&
- ((vertices[i]-vertices[j]).square() > max_distance_sqr))
- max_distance_sqr = (vertices[i]-vertices[j]).square();
- };
+ // the algorithm used simply
+ // traverses all cells and picks
+ // out the boundary vertices. it
+ // may or may not be faster to
+ // simply get all vectors, don't
+ // mark boundary vertices, and
+ // compute the distances thereof,
+ // but at least as the mesh is
+ // refined, it seems better to
+ // first mark boundary nodes, as
+ // marking is O(N) in the number of
+ // cells/vertices, while computing
+ // the maximal distance is O(N*N)
+ const std::vector<Point<spacedim> > &vertices = tria.get_vertices ();
+ std::vector<bool> boundary_vertices (vertices.size(), false);
+
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = tria.begin_active();
+ const typename Triangulation<dim,spacedim>::active_cell_iterator
+ endc = tria.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int face=0; face<GeometryInfo<dim>::faces_per_cell; ++face)
+ if (cell->face(face)->at_boundary ())
+ for (unsigned int i=0; i<GeometryInfo<dim>::vertices_per_face; ++i)
+ boundary_vertices[cell->face(face)->vertex_index(i)] = true;
+
+ // now traverse the list of
+ // boundary vertices and check
+ // distances. since distances are
+ // symmetric, we only have to check
+ // one half
+ double max_distance_sqr = 0;
+ std::vector<bool>::const_iterator pi = boundary_vertices.begin();
+ const unsigned int N = boundary_vertices.size();
+ for (unsigned int i=0; i<N; ++i, ++pi)
+ {
+ std::vector<bool>::const_iterator pj = pi+1;
+ for (unsigned int j=i+1; j<N; ++j, ++pj)
+ if ((*pi==true) && (*pj==true) &&
+ ((vertices[i]-vertices[j]).square() > max_distance_sqr))
+ max_distance_sqr = (vertices[i]-vertices[j]).square();
+ };
- return std::sqrt(max_distance_sqr);
-}
+ return std::sqrt(max_distance_sqr);
+ }
-template <int dim, int spacedim>
-double
-GridTools::volume (const Triangulation<dim, spacedim> &triangulation,
- const Mapping<dim,spacedim> &mapping)
-{
- // get the degree of the mapping if possible. if not, just assume 1
- const unsigned int mapping_degree
- = (dynamic_cast<const MappingQ<dim,spacedim>*>(&mapping) != 0 ?
- dynamic_cast<const MappingQ<dim,spacedim>*>(&mapping)->get_degree() :
- 1);
+ template <int dim, int spacedim>
+ double
+ volume (const Triangulation<dim, spacedim> &triangulation,
+ const Mapping<dim,spacedim> &mapping)
+ {
+ // get the degree of the mapping if possible. if not, just assume 1
+ const unsigned int mapping_degree
+ = (dynamic_cast<const MappingQ<dim,spacedim>*>(&mapping) != 0 ?
+ dynamic_cast<const MappingQ<dim,spacedim>*>(&mapping)->get_degree() :
+ 1);
- // then initialize an appropriate quadrature formula
- const QGauss<dim> quadrature_formula (mapping_degree + 1);
- const unsigned int n_q_points = quadrature_formula.size();
+ // then initialize an appropriate quadrature formula
+ const QGauss<dim> quadrature_formula (mapping_degree + 1);
+ const unsigned int n_q_points = quadrature_formula.size();
- FE_DGQ<dim,spacedim> dummy_fe(0);
- FEValues<dim,spacedim> fe_values (mapping, dummy_fe, quadrature_formula,
- update_JxW_values);
+ FE_DGQ<dim,spacedim> dummy_fe(0);
+ FEValues<dim,spacedim> fe_values (mapping, dummy_fe, quadrature_formula,
+ update_JxW_values);
- typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active(),
- endc = triangulation.end();
+ typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(),
+ endc = triangulation.end();
- double local_volume = 0;
+ double local_volume = 0;
- // compute the integral quantities by quadrature
- for (; cell!=endc; ++cell)
- if (cell->is_locally_owned())
- {
- fe_values.reinit (cell);
- for (unsigned int q=0; q<n_q_points; ++q)
- local_volume += fe_values.JxW(q);
- }
+ // compute the integral quantities by quadrature
+ for (; cell!=endc; ++cell)
+ if (cell->is_locally_owned())
+ {
+ fe_values.reinit (cell);
+ for (unsigned int q=0; q<n_q_points; ++q)
+ local_volume += fe_values.JxW(q);
+ }
- double global_volume = 0;
+ double global_volume = 0;
#ifdef DEAL_II_COMPILER_SUPPORTS_MPI
- if (const parallel::distributed::Triangulation<dim,spacedim>* p_tria
- = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&triangulation))
- MPI_Allreduce (&local_volume, &global_volume, 1, MPI_DOUBLE,
- MPI_SUM,
- p_tria->get_communicator());
- else
- global_volume = local_volume;
+ if (const parallel::distributed::Triangulation<dim,spacedim>* p_tria
+ = dynamic_cast<const parallel::distributed::Triangulation<dim,spacedim>*>(&triangulation))
+ MPI_Allreduce (&local_volume, &global_volume, 1, MPI_DOUBLE,
+ MPI_SUM,
+ p_tria->get_communicator());
+ else
+ global_volume = local_volume;
#else
- global_volume = local_volume;
+ global_volume = local_volume;
#endif
- return global_volume;
-}
+ return global_volume;
+ }
-template <>
-double
-GridTools::cell_measure<3>(const std::vector<Point<3> > &all_vertices,
- const unsigned int (&vertex_indices)[GeometryInfo<3>::vertices_per_cell])
-{
- // note that this is the
- // cell_measure based on the new
- // deal.II numbering. When called
- // from inside GridReordering make
- // sure that you reorder the
- // vertex_indices before
- const double x[8] = { all_vertices[vertex_indices[0]](0),
- all_vertices[vertex_indices[1]](0),
- all_vertices[vertex_indices[2]](0),
- all_vertices[vertex_indices[3]](0),
- all_vertices[vertex_indices[4]](0),
- all_vertices[vertex_indices[5]](0),
- all_vertices[vertex_indices[6]](0),
- all_vertices[vertex_indices[7]](0) };
- const double y[8] = { all_vertices[vertex_indices[0]](1),
- all_vertices[vertex_indices[1]](1),
- all_vertices[vertex_indices[2]](1),
- all_vertices[vertex_indices[3]](1),
- all_vertices[vertex_indices[4]](1),
- all_vertices[vertex_indices[5]](1),
- all_vertices[vertex_indices[6]](1),
- all_vertices[vertex_indices[7]](1) };
- const double z[8] = { all_vertices[vertex_indices[0]](2),
- all_vertices[vertex_indices[1]](2),
- all_vertices[vertex_indices[2]](2),
- all_vertices[vertex_indices[3]](2),
- all_vertices[vertex_indices[4]](2),
- all_vertices[vertex_indices[5]](2),
- all_vertices[vertex_indices[6]](2),
- all_vertices[vertex_indices[7]](2) };
+ template <>
+ double
+ cell_measure<3>(const std::vector<Point<3> > &all_vertices,
+ const unsigned int (&vertex_indices)[GeometryInfo<3>::vertices_per_cell])
+ {
+ // note that this is the
+ // cell_measure based on the new
+ // deal.II numbering. When called
+ // from inside GridReordering make
+ // sure that you reorder the
+ // vertex_indices before
+ const double x[8] = { all_vertices[vertex_indices[0]](0),
+ all_vertices[vertex_indices[1]](0),
+ all_vertices[vertex_indices[2]](0),
+ all_vertices[vertex_indices[3]](0),
+ all_vertices[vertex_indices[4]](0),
+ all_vertices[vertex_indices[5]](0),
+ all_vertices[vertex_indices[6]](0),
+ all_vertices[vertex_indices[7]](0) };
+ const double y[8] = { all_vertices[vertex_indices[0]](1),
+ all_vertices[vertex_indices[1]](1),
+ all_vertices[vertex_indices[2]](1),
+ all_vertices[vertex_indices[3]](1),
+ all_vertices[vertex_indices[4]](1),
+ all_vertices[vertex_indices[5]](1),
+ all_vertices[vertex_indices[6]](1),
+ all_vertices[vertex_indices[7]](1) };
+ const double z[8] = { all_vertices[vertex_indices[0]](2),
+ all_vertices[vertex_indices[1]](2),
+ all_vertices[vertex_indices[2]](2),
+ all_vertices[vertex_indices[3]](2),
+ all_vertices[vertex_indices[4]](2),
+ all_vertices[vertex_indices[5]](2),
+ all_vertices[vertex_indices[6]](2),
+ all_vertices[vertex_indices[7]](2) };
/*
This is the same Maple script as in the barycenter method above
hundred of times.
*/
- const double t3 = y[3]*x[2];
- const double t5 = z[1]*x[5];
- const double t9 = z[3]*x[2];
- const double t11 = x[1]*y[0];
- const double t14 = x[4]*y[0];
- const double t18 = x[5]*y[7];
- const double t20 = y[1]*x[3];
- const double t22 = y[5]*x[4];
- const double t26 = z[7]*x[6];
- const double t28 = x[0]*y[4];
- const double t34 = z[3]*x[1]*y[2]+t3*z[1]-t5*y[7]+y[7]*x[4]*z[6]+t9*y[6]-t11*z[4]-t5*y[3]-t14*z[2]+z[1]*x[4]*y[0]-t18*z[3]+t20*z[0]-t22*z[0]-y[0]*x[5]*z[4]-t26*y[3]+t28*z[2]-t9*y[1]-y[1]*x[4]*z[0]-t11*z[5];
- const double t37 = y[1]*x[0];
- const double t44 = x[1]*y[5];
- const double t46 = z[1]*x[0];
- const double t49 = x[0]*y[2];
- const double t52 = y[5]*x[7];
- const double t54 = x[3]*y[7];
- const double t56 = x[2]*z[0];
- const double t58 = x[3]*y[2];
- const double t64 = -x[6]*y[4]*z[2]-t37*z[2]+t18*z[6]-x[3]*y[6]*z[2]+t11*z[2]+t5*y[0]+t44*z[4]-t46*y[4]-t20*z[7]-t49*z[6]-t22*z[1]+t52*z[3]-t54*z[2]-t56*y[4]-t58*z[0]+y[1]*x[2]*z[0]+t9*y[7]+t37*z[4];
- const double t66 = x[1]*y[7];
- const double t68 = y[0]*x[6];
- const double t70 = x[7]*y[6];
- const double t73 = z[5]*x[4];
- const double t76 = x[6]*y[7];
- const double t90 = x[4]*z[0];
- const double t92 = x[1]*y[3];
- const double t95 = -t66*z[3]-t68*z[2]-t70*z[2]+t26*y[5]-t73*y[6]-t14*z[6]+t76*z[2]-t3*z[6]+x[6]*y[2]*z[4]-z[3]*x[6]*y[2]+t26*y[4]-t44*z[3]-x[1]*y[2]*z[0]+x[5]*y[6]*z[4]+t54*z[5]+t90*y[2]-t92*z[2]+t46*y[2];
- const double t102 = x[2]*y[0];
- const double t107 = y[3]*x[7];
- const double t114 = x[0]*y[6];
- const double t125 = y[0]*x[3]*z[2]-z[7]*x[5]*y[6]-x[2]*y[6]*z[4]+t102*z[6]-t52*z[6]+x[2]*y[4]*z[6]-t107*z[5]-t54*z[6]+t58*z[6]-x[7]*y[4]*z[6]+t37*z[5]-t114*z[4]+t102*z[4]-z[1]*x[2]*y[0]+t28*z[6]-y[5]*x[6]*z[4]-z[5]*x[1]*y[4]-t73*y[7];
- const double t129 = z[0]*x[6];
- const double t133 = y[1]*x[7];
- const double t145 = y[1]*x[5];
- const double t156 = t90*y[6]-t129*y[4]+z[7]*x[2]*y[6]-t133*z[5]+x[5]*y[3]*z[7]-t26*y[2]-t70*z[3]+t46*y[3]+z[5]*x[7]*y[4]+z[7]*x[3]*y[6]-t49*z[4]+t145*z[7]-x[2]*y[7]*z[6]+t70*z[5]+t66*z[5]-z[7]*x[4]*y[6]+t18*z[4]+x[1]*y[4]*z[0];
- const double t160 = x[5]*y[4];
- const double t165 = z[1]*x[7];
- const double t178 = z[1]*x[3];
- const double t181 = t107*z[6]+t22*z[7]+t76*z[3]+t160*z[1]-x[4]*y[2]*z[6]+t70*z[4]+t165*y[5]+x[7]*y[2]*z[6]-t76*z[5]-t76*z[4]+t133*z[3]-t58*z[1]+y[5]*x[0]*z[4]+t114*z[2]-t3*z[7]+t20*z[2]+t178*y[7]+t129*y[2];
- const double t207 = t92*z[7]+t22*z[6]+z[3]*x[0]*y[2]-x[0]*y[3]*z[2]-z[3]*x[7]*y[2]-t165*y[3]-t9*y[0]+t58*z[7]+y[3]*x[6]*z[2]+t107*z[2]+t73*y[0]-x[3]*y[5]*z[7]+t3*z[0]-t56*y[6]-z[5]*x[0]*y[4]+t73*y[1]-t160*z[6]+t160*z[0];
- const double t228 = -t44*z[7]+z[5]*x[6]*y[4]-t52*z[4]-t145*z[4]+t68*z[4]+t92*z[5]-t92*z[0]+t11*z[3]+t44*z[0]+t178*y[5]-t46*y[5]-t178*y[0]-t145*z[0]-t20*z[5]-t37*z[3]-t160*z[7]+t145*z[3]+x[4]*y[6]*z[2];
-
- return (t34+t64+t95+t125+t156+t181+t207+t228)/12.;
-}
+ const double t3 = y[3]*x[2];
+ const double t5 = z[1]*x[5];
+ const double t9 = z[3]*x[2];
+ const double t11 = x[1]*y[0];
+ const double t14 = x[4]*y[0];
+ const double t18 = x[5]*y[7];
+ const double t20 = y[1]*x[3];
+ const double t22 = y[5]*x[4];
+ const double t26 = z[7]*x[6];
+ const double t28 = x[0]*y[4];
+ const double t34 = z[3]*x[1]*y[2]+t3*z[1]-t5*y[7]+y[7]*x[4]*z[6]+t9*y[6]-t11*z[4]-t5*y[3]-t14*z[2]+z[1]*x[4]*y[0]-t18*z[3]+t20*z[0]-t22*z[0]-y[0]*x[5]*z[4]-t26*y[3]+t28*z[2]-t9*y[1]-y[1]*x[4]*z[0]-t11*z[5];
+ const double t37 = y[1]*x[0];
+ const double t44 = x[1]*y[5];
+ const double t46 = z[1]*x[0];
+ const double t49 = x[0]*y[2];
+ const double t52 = y[5]*x[7];
+ const double t54 = x[3]*y[7];
+ const double t56 = x[2]*z[0];
+ const double t58 = x[3]*y[2];
+ const double t64 = -x[6]*y[4]*z[2]-t37*z[2]+t18*z[6]-x[3]*y[6]*z[2]+t11*z[2]+t5*y[0]+t44*z[4]-t46*y[4]-t20*z[7]-t49*z[6]-t22*z[1]+t52*z[3]-t54*z[2]-t56*y[4]-t58*z[0]+y[1]*x[2]*z[0]+t9*y[7]+t37*z[4];
+ const double t66 = x[1]*y[7];
+ const double t68 = y[0]*x[6];
+ const double t70 = x[7]*y[6];
+ const double t73 = z[5]*x[4];
+ const double t76 = x[6]*y[7];
+ const double t90 = x[4]*z[0];
+ const double t92 = x[1]*y[3];
+ const double t95 = -t66*z[3]-t68*z[2]-t70*z[2]+t26*y[5]-t73*y[6]-t14*z[6]+t76*z[2]-t3*z[6]+x[6]*y[2]*z[4]-z[3]*x[6]*y[2]+t26*y[4]-t44*z[3]-x[1]*y[2]*z[0]+x[5]*y[6]*z[4]+t54*z[5]+t90*y[2]-t92*z[2]+t46*y[2];
+ const double t102 = x[2]*y[0];
+ const double t107 = y[3]*x[7];
+ const double t114 = x[0]*y[6];
+ const double t125 = y[0]*x[3]*z[2]-z[7]*x[5]*y[6]-x[2]*y[6]*z[4]+t102*z[6]-t52*z[6]+x[2]*y[4]*z[6]-t107*z[5]-t54*z[6]+t58*z[6]-x[7]*y[4]*z[6]+t37*z[5]-t114*z[4]+t102*z[4]-z[1]*x[2]*y[0]+t28*z[6]-y[5]*x[6]*z[4]-z[5]*x[1]*y[4]-t73*y[7];
+ const double t129 = z[0]*x[6];
+ const double t133 = y[1]*x[7];
+ const double t145 = y[1]*x[5];
+ const double t156 = t90*y[6]-t129*y[4]+z[7]*x[2]*y[6]-t133*z[5]+x[5]*y[3]*z[7]-t26*y[2]-t70*z[3]+t46*y[3]+z[5]*x[7]*y[4]+z[7]*x[3]*y[6]-t49*z[4]+t145*z[7]-x[2]*y[7]*z[6]+t70*z[5]+t66*z[5]-z[7]*x[4]*y[6]+t18*z[4]+x[1]*y[4]*z[0];
+ const double t160 = x[5]*y[4];
+ const double t165 = z[1]*x[7];
+ const double t178 = z[1]*x[3];
+ const double t181 = t107*z[6]+t22*z[7]+t76*z[3]+t160*z[1]-x[4]*y[2]*z[6]+t70*z[4]+t165*y[5]+x[7]*y[2]*z[6]-t76*z[5]-t76*z[4]+t133*z[3]-t58*z[1]+y[5]*x[0]*z[4]+t114*z[2]-t3*z[7]+t20*z[2]+t178*y[7]+t129*y[2];
+ const double t207 = t92*z[7]+t22*z[6]+z[3]*x[0]*y[2]-x[0]*y[3]*z[2]-z[3]*x[7]*y[2]-t165*y[3]-t9*y[0]+t58*z[7]+y[3]*x[6]*z[2]+t107*z[2]+t73*y[0]-x[3]*y[5]*z[7]+t3*z[0]-t56*y[6]-z[5]*x[0]*y[4]+t73*y[1]-t160*z[6]+t160*z[0];
+ const double t228 = -t44*z[7]+z[5]*x[6]*y[4]-t52*z[4]-t145*z[4]+t68*z[4]+t92*z[5]-t92*z[0]+t11*z[3]+t44*z[0]+t178*y[5]-t46*y[5]-t178*y[0]-t145*z[0]-t20*z[5]-t37*z[3]-t160*z[7]+t145*z[3]+x[4]*y[6]*z[2];
+
+ return (t34+t64+t95+t125+t156+t181+t207+t228)/12.;
+ }
-template <>
-double
-GridTools::cell_measure(const std::vector<Point<2> > &all_vertices,
- const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell])
-{
+ template <>
+ double
+ cell_measure(const std::vector<Point<2> > &all_vertices,
+ const unsigned int (&vertex_indices) [GeometryInfo<2>::vertices_per_cell])
+ {
/*
Get the computation of the measure by this little Maple script. We
use the blinear mapping of the unit quad to the real quad. However,
additional optimizaton: divide by 2 only one time
*/
- const double x[4] = { all_vertices[vertex_indices[0]](0),
- all_vertices[vertex_indices[1]](0),
- all_vertices[vertex_indices[2]](0),
- all_vertices[vertex_indices[3]](0)};
+ const double x[4] = { all_vertices[vertex_indices[0]](0),
+ all_vertices[vertex_indices[1]](0),
+ all_vertices[vertex_indices[2]](0),
+ all_vertices[vertex_indices[3]](0)};
- const double y[4] = { all_vertices[vertex_indices[0]](1),
- all_vertices[vertex_indices[1]](1),
- all_vertices[vertex_indices[2]](1),
- all_vertices[vertex_indices[3]](1)};
+ const double y[4] = { all_vertices[vertex_indices[0]](1),
+ all_vertices[vertex_indices[1]](1),
+ all_vertices[vertex_indices[2]](1),
+ all_vertices[vertex_indices[3]](1)};
- return (-x[1]*y[0]+x[1]*y[3]+y[0]*x[2]+x[0]*y[1]-x[0]*y[2]-y[1]*x[3]-x[2]*y[3]+x[3]*y[2])/2;
+ return (-x[1]*y[0]+x[1]*y[3]+y[0]*x[2]+x[0]*y[1]-x[0]*y[2]-y[1]*x[3]-x[2]*y[3]+x[3]*y[2])/2;
-}
+ }
-template <int dim>
-double
-GridTools::cell_measure(const std::vector<Point<dim> > &,
- const unsigned int (&) [GeometryInfo<dim>::vertices_per_cell])
-{
- Assert(false, ExcNotImplemented());
- return 0.;
-}
+ template <int dim>
+ double
+ cell_measure(const std::vector<Point<dim> > &,
+ const unsigned int (&) [GeometryInfo<dim>::vertices_per_cell])
+ {
+ Assert(false, ExcNotImplemented());
+ return 0.;
+ }
-template <int dim, int spacedim>
-void
-GridTools::delete_unused_vertices (std::vector<Point<spacedim> > &vertices,
- std::vector<CellData<dim> > &cells,
- SubCellData &subcelldata)
-{
- // first check which vertices are
- // actually used
- std::vector<bool> vertex_used (vertices.size(), false);
- for (unsigned int c=0; c<cells.size(); ++c)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- vertex_used[cells[c].vertices[v]] = true;
-
- // then renumber the vertices that
- // are actually used in the same
- // order as they were beforehand
- const unsigned int invalid_vertex = numbers::invalid_unsigned_int;
- std::vector<unsigned int> new_vertex_numbers (vertices.size(), invalid_vertex);
- unsigned int next_free_number = 0;
- for (unsigned int i=0; i<vertices.size(); ++i)
- if (vertex_used[i] == true)
- {
- new_vertex_numbers[i] = next_free_number;
- ++next_free_number;
- };
-
- // next replace old vertex numbers
- // by the new ones
- for (unsigned int c=0; c<cells.size(); ++c)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- cells[c].vertices[v] = new_vertex_numbers[cells[c].vertices[v]];
-
- // same for boundary data
- for (unsigned int c=0; c<subcelldata.boundary_lines.size(); ++c)
- for (unsigned int v=0; v<GeometryInfo<1>::vertices_per_cell; ++v)
- subcelldata.boundary_lines[c].vertices[v]
- = new_vertex_numbers[subcelldata.boundary_lines[c].vertices[v]];
- for (unsigned int c=0; c<subcelldata.boundary_quads.size(); ++c)
- for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
- subcelldata.boundary_quads[c].vertices[v]
- = new_vertex_numbers[subcelldata.boundary_quads[c].vertices[v]];
-
- // finally copy over the vertices
- // which we really need to a new
- // array and replace the old one by
- // the new one
- std::vector<Point<spacedim> > tmp;
- tmp.reserve (std::count(vertex_used.begin(), vertex_used.end(), true));
- for (unsigned int v=0; v<vertices.size(); ++v)
- if (vertex_used[v] == true)
- tmp.push_back (vertices[v]);
- swap (vertices, tmp);
-}
+ template <int dim, int spacedim>
+ void
+ delete_unused_vertices (std::vector<Point<spacedim> > &vertices,
+ std::vector<CellData<dim> > &cells,
+ SubCellData &subcelldata)
+ {
+ // first check which vertices are
+ // actually used
+ std::vector<bool> vertex_used (vertices.size(), false);
+ for (unsigned int c=0; c<cells.size(); ++c)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ vertex_used[cells[c].vertices[v]] = true;
+
+ // then renumber the vertices that
+ // are actually used in the same
+ // order as they were beforehand
+ const unsigned int invalid_vertex = numbers::invalid_unsigned_int;
+ std::vector<unsigned int> new_vertex_numbers (vertices.size(), invalid_vertex);
+ unsigned int next_free_number = 0;
+ for (unsigned int i=0; i<vertices.size(); ++i)
+ if (vertex_used[i] == true)
+ {
+ new_vertex_numbers[i] = next_free_number;
+ ++next_free_number;
+ };
+
+ // next replace old vertex numbers
+ // by the new ones
+ for (unsigned int c=0; c<cells.size(); ++c)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ cells[c].vertices[v] = new_vertex_numbers[cells[c].vertices[v]];
+
+ // same for boundary data
+ for (unsigned int c=0; c<subcelldata.boundary_lines.size(); ++c)
+ for (unsigned int v=0; v<GeometryInfo<1>::vertices_per_cell; ++v)
+ subcelldata.boundary_lines[c].vertices[v]
+ = new_vertex_numbers[subcelldata.boundary_lines[c].vertices[v]];
+ for (unsigned int c=0; c<subcelldata.boundary_quads.size(); ++c)
+ for (unsigned int v=0; v<GeometryInfo<2>::vertices_per_cell; ++v)
+ subcelldata.boundary_quads[c].vertices[v]
+ = new_vertex_numbers[subcelldata.boundary_quads[c].vertices[v]];
+
+ // finally copy over the vertices
+ // which we really need to a new
+ // array and replace the old one by
+ // the new one
+ std::vector<Point<spacedim> > tmp;
+ tmp.reserve (std::count(vertex_used.begin(), vertex_used.end(), true));
+ for (unsigned int v=0; v<vertices.size(); ++v)
+ if (vertex_used[v] == true)
+ tmp.push_back (vertices[v]);
+ swap (vertices, tmp);
+ }
-template <int dim, int spacedim>
-void
-GridTools::delete_duplicated_vertices (std::vector<Point<spacedim> > &vertices,
- std::vector<CellData<dim> > &cells,
- SubCellData &subcelldata,
- std::vector<unsigned int> &considered_vertices,
- double tol)
-{
- // create a vector of vertex
- // indices. initialize it to the identity,
- // later on change that if necessary.
- std::vector<unsigned int> new_vertex_numbers(vertices.size());
- for (unsigned int i=0; i<vertices.size(); ++i)
- new_vertex_numbers[i]=i;
-
- // if the considered_vertices vector is
- // empty, consider all vertices
- if (considered_vertices.size()==0)
- considered_vertices=new_vertex_numbers;
-
- // now loop over all vertices to be
- // considered and try to find an identical
- // one
- for (unsigned int i=0; i<considered_vertices.size(); ++i)
- {
- if (new_vertex_numbers[considered_vertices[i]]!=considered_vertices[i])
- // this vertex has been identified with
- // another one already, skip it in the
- // test
- continue;
- // this vertex is not identified with
- // another one so far. search in the list
- // of remaining vertices. if a duplicate
- // vertex is found, set the new vertex
- // index for that vertex to this vertex'
- // index.
- for (unsigned int j=i+1; j<considered_vertices.size(); ++j)
- {
- bool equal=true;
- for (unsigned int d=0; d<dim; ++d)
- equal &= (fabs(vertices[considered_vertices[j]](d)-vertices[considered_vertices[i]](d))<tol);
- if (equal)
- {
- new_vertex_numbers[considered_vertices[j]]=considered_vertices[i];
- // we do not suppose, that there might be another duplicate
- // vertex, so break here
- break;
- }
- }
- }
+ template <int dim, int spacedim>
+ void
+ delete_duplicated_vertices (std::vector<Point<spacedim> > &vertices,
+ std::vector<CellData<dim> > &cells,
+ SubCellData &subcelldata,
+ std::vector<unsigned int> &considered_vertices,
+ double tol)
+ {
+ // create a vector of vertex
+ // indices. initialize it to the identity,
+ // later on change that if necessary.
+ std::vector<unsigned int> new_vertex_numbers(vertices.size());
+ for (unsigned int i=0; i<vertices.size(); ++i)
+ new_vertex_numbers[i]=i;
+
+ // if the considered_vertices vector is
+ // empty, consider all vertices
+ if (considered_vertices.size()==0)
+ considered_vertices=new_vertex_numbers;
+
+ // now loop over all vertices to be
+ // considered and try to find an identical
+ // one
+ for (unsigned int i=0; i<considered_vertices.size(); ++i)
+ {
+ if (new_vertex_numbers[considered_vertices[i]]!=considered_vertices[i])
+ // this vertex has been identified with
+ // another one already, skip it in the
+ // test
+ continue;
+ // this vertex is not identified with
+ // another one so far. search in the list
+ // of remaining vertices. if a duplicate
+ // vertex is found, set the new vertex
+ // index for that vertex to this vertex'
+ // index.
+ for (unsigned int j=i+1; j<considered_vertices.size(); ++j)
+ {
+ bool equal=true;
+ for (unsigned int d=0; d<dim; ++d)
+ equal &= (fabs(vertices[considered_vertices[j]](d)-vertices[considered_vertices[i]](d))<tol);
+ if (equal)
+ {
+ new_vertex_numbers[considered_vertices[j]]=considered_vertices[i];
+ // we do not suppose, that there might be another duplicate
+ // vertex, so break here
+ break;
+ }
+ }
+ }
- // now we got a renumbering list. simply
- // renumber all vertices (non-duplicate
- // vertices get renumbered to themselves, so
- // nothing bad happens). after that, the
- // duplicate vertices will be unused, so call
- // delete_unused_vertices() to do that part
- // of the job.
- for (unsigned int c=0; c<cells.size(); ++c)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- cells[c].vertices[v]=new_vertex_numbers[cells[c].vertices[v]];
-
- delete_unused_vertices(vertices,cells,subcelldata);
-}
+ // now we got a renumbering list. simply
+ // renumber all vertices (non-duplicate
+ // vertices get renumbered to themselves, so
+ // nothing bad happens). after that, the
+ // duplicate vertices will be unused, so call
+ // delete_unused_vertices() to do that part
+ // of the job.
+ for (unsigned int c=0; c<cells.size(); ++c)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ cells[c].vertices[v]=new_vertex_numbers[cells[c].vertices[v]];
+
+ delete_unused_vertices(vertices,cells,subcelldata);
+ }
#else
namespace
#endif
-{
- template <int spacedim>
- class ShiftPoint
{
- public:
- ShiftPoint (const Point<spacedim> &shift)
- :
- shift(shift)
- {}
- Point<spacedim> operator() (const Point<spacedim> p) const
- {
- return p+shift;
- }
- private:
- const Point<spacedim> shift;
- };
+ template <int spacedim>
+ class ShiftPoint
+ {
+ public:
+ ShiftPoint (const Point<spacedim> &shift)
+ :
+ shift(shift)
+ {}
+ Point<spacedim> operator() (const Point<spacedim> p) const
+ {
+ return p+shift;
+ }
+ private:
+ const Point<spacedim> shift;
+ };
- // the following class is only
- // needed in 2d, so avoid trouble
- // with compilers warning otherwise
- class Rotate2d
- {
- public:
- Rotate2d (const double angle)
- :
- angle(angle)
- {}
- Point<2> operator() (const Point<2> &p) const
- {
- return Point<2> (std::cos(angle)*p(0) - std::sin(angle) * p(1),
- std::sin(angle)*p(0) + std::cos(angle) * p(1));
- }
- private:
- const double angle;
- };
+ // the following class is only
+ // needed in 2d, so avoid trouble
+ // with compilers warning otherwise
+ class Rotate2d
+ {
+ public:
+ Rotate2d (const double angle)
+ :
+ angle(angle)
+ {}
+ Point<2> operator() (const Point<2> &p) const
+ {
+ return Point<2> (std::cos(angle)*p(0) - std::sin(angle) * p(1),
+ std::sin(angle)*p(0) + std::cos(angle) * p(1));
+ }
+ private:
+ const double angle;
+ };
- template <int spacedim>
- class ScalePoint
- {
- public:
- ScalePoint (const double factor)
- :
- factor(factor)
- {}
- Point<spacedim> operator() (const Point<spacedim> p) const
- {
- return p*factor;
- }
- private:
- const double factor;
- };
-}
+ template <int spacedim>
+ class ScalePoint
+ {
+ public:
+ ScalePoint (const double factor)
+ :
+ factor(factor)
+ {}
+ Point<spacedim> operator() (const Point<spacedim> p) const
+ {
+ return p*factor;
+ }
+ private:
+ const double factor;
+ };
+ }
-template <int dim, int spacedim>
-void
-GridTools::shift (const Point<spacedim> &shift_vector,
- Triangulation<dim, spacedim> &triangulation)
-{
+ template <int dim, int spacedim>
+ void
+ shift (const Point<spacedim> &shift_vector,
+ Triangulation<dim, spacedim> &triangulation)
+ {
#ifdef DEAL_II_ANON_NAMESPACE_BOGUS_WARNING
- transform (TRANS::ShiftPoint<spacedim>(shift_vector), triangulation);
+ transform (TRANS::ShiftPoint<spacedim>(shift_vector), triangulation);
#else
- transform (ShiftPoint<spacedim>(shift_vector), triangulation);
+ transform (ShiftPoint<spacedim>(shift_vector), triangulation);
#endif
-}
+ }
-void
-GridTools::rotate (const double angle,
- Triangulation<2> &triangulation)
-{
+ void
+ rotate (const double angle,
+ Triangulation<2> &triangulation)
+ {
#ifdef DEAL_II_ANON_NAMESPACE_BOGUS_WARNING
- transform (TRANS::Rotate2d(angle), triangulation);
+ transform (TRANS::Rotate2d(angle), triangulation);
#else
- transform (Rotate2d(angle), triangulation);
+ transform (Rotate2d(angle), triangulation);
#endif
-}
+ }
-template <int dim, int spacedim>
-void
-GridTools::scale (const double scaling_factor,
- Triangulation<dim, spacedim> &triangulation)
-{
- Assert (scaling_factor>0, ExcScalingFactorNotPositive (scaling_factor));
+ template <int dim, int spacedim>
+ void
+ scale (const double scaling_factor,
+ Triangulation<dim, spacedim> &triangulation)
+ {
+ Assert (scaling_factor>0, ExcScalingFactorNotPositive (scaling_factor));
#ifdef DEAL_II_ANON_NAMESPACE_BOGUS_WARNING
- transform (TRANS::ScalePoint<spacedim>(scaling_factor), triangulation);
+ transform (TRANS::ScalePoint<spacedim>(scaling_factor), triangulation);
#else
- transform (ScalePoint<spacedim>(scaling_factor), triangulation);
+ transform (ScalePoint<spacedim>(scaling_factor), triangulation);
#endif
-}
+ }
-template <int dim, template <int, int> class Container, int spacedim>
-unsigned int
-GridTools::find_closest_vertex (const Container<dim,spacedim> &container,
- const Point<spacedim> &p)
-{
- // first get the underlying
- // triangulation from the
- // container and determine vertices
- // and used vertices
- const Triangulation<dim, spacedim> &tria = get_tria(container);
-
- const std::vector< Point<spacedim> > &vertices = tria.get_vertices();
- const std::vector< bool > &used = tria.get_used_vertices();
-
- // At the beginning, the first
- // used vertex is the closest one
- std::vector<bool>::const_iterator first =
- std::find(used.begin(), used.end(), true);
-
- // Assert that at least one vertex
- // is actually used
- Assert(first != used.end(), ExcInternalError());
-
- unsigned int best_vertex = std::distance(used.begin(), first);
- double best_dist = (p - vertices[best_vertex]).square();
-
- // For all remaining vertices, test
- // whether they are any closer
- for(unsigned int j = best_vertex+1; j < vertices.size(); j++)
- if(used[j])
- {
- double dist = (p - vertices[j]).square();
- if(dist < best_dist)
+ template <int dim, template <int, int> class Container, int spacedim>
+ unsigned int
+ find_closest_vertex (const Container<dim,spacedim> &container,
+ const Point<spacedim> &p)
+ {
+ // first get the underlying
+ // triangulation from the
+ // container and determine vertices
+ // and used vertices
+ const Triangulation<dim, spacedim> &tria = get_tria(container);
+
+ const std::vector< Point<spacedim> > &vertices = tria.get_vertices();
+ const std::vector< bool > &used = tria.get_used_vertices();
+
+ // At the beginning, the first
+ // used vertex is the closest one
+ std::vector<bool>::const_iterator first =
+ std::find(used.begin(), used.end(), true);
+
+ // Assert that at least one vertex
+ // is actually used
+ Assert(first != used.end(), ExcInternalError());
+
+ unsigned int best_vertex = std::distance(used.begin(), first);
+ double best_dist = (p - vertices[best_vertex]).square();
+
+ // For all remaining vertices, test
+ // whether they are any closer
+ for(unsigned int j = best_vertex+1; j < vertices.size(); j++)
+ if(used[j])
+ {
+ double dist = (p - vertices[j]).square();
+ if(dist < best_dist)
+ {
+ best_vertex = j;
+ best_dist = dist;
+ }
+ }
+
+ return best_vertex;
+ }
+
+
+ template<int dim, template<int, int> class Container, int spacedim>
+ std::vector<typename Container<dim,spacedim>::active_cell_iterator>
+ find_cells_adjacent_to_vertex(const Container<dim,spacedim> &container,
+ const unsigned int vertex)
+ {
+ // make sure that the given vertex is
+ // an active vertex of the underlying
+ // triangulation
+ Assert(vertex < get_tria(container).n_vertices(),
+ ExcIndexRange(0,get_tria(container).n_vertices(),vertex));
+ Assert(get_tria(container).get_used_vertices()[vertex],
+ ExcVertexNotUsed(vertex));
+
+ // We use a set instead of a vector
+ // to ensure that cells are inserted only
+ // once. A bug in the previous version
+ // prevented some cases to be
+ // treated correctly
+ std::set<typename Container<dim,spacedim>::active_cell_iterator> adj_cells_set;
+
+ typename Container<dim,spacedim>::active_cell_iterator
+ cell = container.begin_active(),
+ endc = container.end();
+
+ // go through all active cells and look
+ // if the vertex is part of that cell
+ for (; cell != endc; ++cell)
+ for (unsigned v = 0; v < GeometryInfo<dim>::vertices_per_cell; v++)
+ if (cell->vertex_index(v) == vertex)
{
- best_vertex = j;
- best_dist = dist;
+ // OK, we found a cell that contains
+ // the particular vertex. We add it
+ // to the list.
+ adj_cells_set.insert(cell);
+
+ // Now we need to make sure that the
+ // vertex is not a locally refined
+ // vertex not being part of the
+ // neighboring cells. So we loop over
+ // all faces to which this vertex
+ // belongs, check the level of
+ // the neighbor, and if it is coarser,
+ // then check whether the vertex is
+ // part of that neighbor or not.
+ for (unsigned vface = 0; vface < dim; vface++)
+ {
+ const unsigned face =
+ GeometryInfo<dim>::vertex_to_face[v][vface];
+ if (!cell->at_boundary(face))
+ {
+ typename Container<dim,spacedim>::cell_iterator
+ nb = cell->neighbor(face);
+
+ // Here we
+ // check
+ // whether
+ // the
+ // neighbor
+ // is
+ // coarser. If
+ // it is, we
+ // search
+ // for the
+ // vertex in
+ // this
+ // coarser
+ // cell and
+ // only if
+ // not found
+ // we will
+ // add the
+ // coarser
+ // cell
+ // itself
+ if (nb->level() < cell->level())
+ {
+ bool found = false;
+ for (unsigned v=0; v<GeometryInfo<dim>::vertices_per_cell; v++)
+ if (nb->vertex_index(v) == vertex)
+ {
+ found = true;
+ break;
+ }
+ if (!found)
+ adj_cells_set.insert(nb);
+ }
+ }
+ }
+
+ break;
}
- }
- return best_vertex;
-}
+ std::vector<typename Container<dim,spacedim>::active_cell_iterator>
+ adjacent_cells;
+ // We now produce the output vector
+ // from the set that we assembled above.
+ typename std::set<typename Container<dim,spacedim>::active_cell_iterator>::iterator
+ it = adj_cells_set.begin(),
+ endit = adj_cells_set.end();
+ for(; it != endit; ++it)
+ adjacent_cells.push_back(*it);
-template<int dim, template<int, int> class Container, int spacedim>
-std::vector<typename Container<dim,spacedim>::active_cell_iterator>
-GridTools::find_cells_adjacent_to_vertex(const Container<dim,spacedim> &container,
- const unsigned int vertex)
-{
- // make sure that the given vertex is
- // an active vertex of the underlying
- // triangulation
- Assert(vertex < get_tria(container).n_vertices(),
- ExcIndexRange(0,get_tria(container).n_vertices(),vertex));
- Assert(get_tria(container).get_used_vertices()[vertex],
- ExcVertexNotUsed(vertex));
-
- // We use a set instead of a vector
- // to ensure that cells are inserted only
- // once. A bug in the previous version
- // prevented some cases to be
- // treated correctly
- std::set<typename Container<dim,spacedim>::active_cell_iterator> adj_cells_set;
- typename Container<dim,spacedim>::active_cell_iterator
- cell = container.begin_active(),
- endc = container.end();
-
- // go through all active cells and look
- // if the vertex is part of that cell
- for (; cell != endc; ++cell)
- for (unsigned v = 0; v < GeometryInfo<dim>::vertices_per_cell; v++)
- if (cell->vertex_index(v) == vertex)
- {
- // OK, we found a cell that contains
- // the particular vertex. We add it
- // to the list.
- adj_cells_set.insert(cell);
-
- // Now we need to make sure that the
- // vertex is not a locally refined
- // vertex not being part of the
- // neighboring cells. So we loop over
- // all faces to which this vertex
- // belongs, check the level of
- // the neighbor, and if it is coarser,
- // then check whether the vertex is
- // part of that neighbor or not.
- for (unsigned vface = 0; vface < dim; vface++)
- {
- const unsigned face =
- GeometryInfo<dim>::vertex_to_face[v][vface];
- if (!cell->at_boundary(face))
- {
- typename Container<dim,spacedim>::cell_iterator
- nb = cell->neighbor(face);
-
- // Here we
- // check
- // whether
- // the
- // neighbor
- // is
- // coarser. If
- // it is, we
- // search
- // for the
- // vertex in
- // this
- // coarser
- // cell and
- // only if
- // not found
- // we will
- // add the
- // coarser
- // cell
- // itself
- if (nb->level() < cell->level())
- {
- bool found = false;
- for (unsigned v=0; v<GeometryInfo<dim>::vertices_per_cell; v++)
- if (nb->vertex_index(v) == vertex)
- {
- found = true;
- break;
- }
- if (!found)
- adj_cells_set.insert(nb);
- }
- }
- }
+ Assert(adjacent_cells.size() > 0, ExcInternalError());
- break;
- }
+ return adjacent_cells;
+ }
- std::vector<typename Container<dim,spacedim>::active_cell_iterator>
- adjacent_cells;
- // We now produce the output vector
- // from the set that we assembled above.
- typename std::set<typename Container<dim,spacedim>::active_cell_iterator>::iterator
- it = adj_cells_set.begin(),
- endit = adj_cells_set.end();
- for(; it != endit; ++it)
- adjacent_cells.push_back(*it);
+ template <int dim, template<int, int> class Container, int spacedim>
+ typename Container<dim,spacedim>::active_cell_iterator
+ find_active_cell_around_point (const Container<dim,spacedim> &container,
+ const Point<spacedim> &p)
+ {
+ return find_active_cell_around_point(StaticMappingQ1<dim,spacedim>::mapping,
+ container, p).first;
+ }
- Assert(adjacent_cells.size() > 0, ExcInternalError());
- return adjacent_cells;
-}
+ template <int dim, template <int, int> class Container, int spacedim>
+ std::pair<typename Container<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ find_active_cell_around_point (const Mapping<dim,spacedim> &mapping,
+ const Container<dim,spacedim> &container,
+ const Point<spacedim> &p)
+ {
+ typedef typename Container<dim,spacedim>::active_cell_iterator cell_iterator;
+ // The best distance is set to the
+ // maximum allowable distance from
+ // the unit cell; we assume a
+ // max. deviation of 1e-10
+ double best_distance = 1e-10;
+ int best_level = -1;
+ std::pair<cell_iterator, Point<spacedim> > best_cell;
+ // Find closest vertex and determine
+ // all adjacent cells
+ unsigned int vertex = find_closest_vertex(container, p);
-template <int dim, template<int, int> class Container, int spacedim>
-typename Container<dim,spacedim>::active_cell_iterator
-GridTools::find_active_cell_around_point (const Container<dim,spacedim> &container,
- const Point<spacedim> &p)
-{
- return find_active_cell_around_point(StaticMappingQ1<dim,spacedim>::mapping,
- container, p).first;
-}
+ std::vector<cell_iterator> adjacent_cells =
+ find_cells_adjacent_to_vertex(container, vertex);
+ typename std::vector<cell_iterator>::const_iterator
+ cell = adjacent_cells.begin(),
+ endc = adjacent_cells.end();
-template <int dim, template <int, int> class Container, int spacedim>
-std::pair<typename Container<dim,spacedim>::active_cell_iterator, Point<spacedim> >
-GridTools::find_active_cell_around_point (const Mapping<dim,spacedim> &mapping,
- const Container<dim,spacedim> &container,
- const Point<spacedim> &p)
-{
- typedef typename Container<dim,spacedim>::active_cell_iterator cell_iterator;
+ for(; cell != endc; ++cell)
+ {
+ const Point<spacedim> p_cell = mapping.transform_real_to_unit_cell(*cell, p);
+
+ // calculate the infinity norm of
+ // the distance vector to the unit cell.
+ const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_cell);
+
+ // We compare if the point is inside the
+ // unit cell (or at least not too far
+ // outside). If it is, it is also checked
+ // that the cell has a more refined state
+ if (dist < best_distance ||
+ (dist == best_distance && (*cell)->level() > best_level))
+ {
+ best_distance = dist;
+ best_level = (*cell)->level();
+ best_cell = std::make_pair(*cell, p_cell);
+ }
+ }
- // The best distance is set to the
- // maximum allowable distance from
- // the unit cell; we assume a
- // max. deviation of 1e-10
- double best_distance = 1e-10;
- int best_level = -1;
- std::pair<cell_iterator, Point<spacedim> > best_cell;
+ Assert (best_cell.first.state() == IteratorState::valid,
+ ExcPointNotFound<dim>(p));
- // Find closest vertex and determine
- // all adjacent cells
- unsigned int vertex = find_closest_vertex(container, p);
+ return best_cell;
+ }
- std::vector<cell_iterator> adjacent_cells =
- find_cells_adjacent_to_vertex(container, vertex);
- typename std::vector<cell_iterator>::const_iterator
- cell = adjacent_cells.begin(),
- endc = adjacent_cells.end();
- for(; cell != endc; ++cell)
- {
- const Point<spacedim> p_cell = mapping.transform_real_to_unit_cell(*cell, p);
-
- // calculate the infinity norm of
- // the distance vector to the unit cell.
- const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_cell);
-
- // We compare if the point is inside the
- // unit cell (or at least not too far
- // outside). If it is, it is also checked
- // that the cell has a more refined state
- if (dist < best_distance ||
- (dist == best_distance && (*cell)->level() > best_level))
- {
- best_distance = dist;
- best_level = (*cell)->level();
- best_cell = std::make_pair(*cell, p_cell);
- }
- }
+ template <int dim, int spacedim>
+ std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
+ find_active_cell_around_point (const hp::MappingCollection<dim,spacedim> &mapping,
+ const hp::DoFHandler<dim,spacedim> &container,
+ const Point<spacedim> &p)
+ {
+ typedef typename hp::DoFHandler<dim,spacedim>::active_cell_iterator cell_iterator;
- Assert (best_cell.first.state() == IteratorState::valid,
- ExcPointNotFound<dim>(p));
+ // The best distance is set to the
+ // maximum allowable distance from
+ // the unit cell; we assume a
+ // max. deviation of 1e-10
+ double best_distance = 1e-10;
+ int best_level = -1;
+ std::pair<cell_iterator, Point<spacedim> > best_cell;
- return best_cell;
-}
+ // Find closest vertex and determine
+ // all adjacent cells
+ unsigned int vertex = find_closest_vertex(container, p);
+ std::vector<cell_iterator> adjacent_cells =
+ find_cells_adjacent_to_vertex(container, vertex);
+ typename std::vector<cell_iterator>::const_iterator
+ cell = adjacent_cells.begin(),
+ endc = adjacent_cells.end();
-template <int dim, int spacedim>
-std::pair<typename hp::DoFHandler<dim,spacedim>::active_cell_iterator, Point<spacedim> >
-GridTools::find_active_cell_around_point (const hp::MappingCollection<dim,spacedim> &mapping,
- const hp::DoFHandler<dim,spacedim> &container,
- const Point<spacedim> &p)
-{
- typedef typename hp::DoFHandler<dim,spacedim>::active_cell_iterator cell_iterator;
+ for(; cell != endc; ++cell)
+ {
+ const Point<spacedim> p_cell
+ = mapping[(*cell)->active_fe_index()].transform_real_to_unit_cell(*cell, p);
+
+ // calculate the infinity norm of
+ // the distance vector to the unit cell.
+ const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_cell);
+
+ // We compare if the point is inside the
+ // unit cell (or at least not too far
+ // outside). If it is, it is also checked
+ // that the cell has a more refined state
+ if (dist < best_distance ||
+ (dist == best_distance && (*cell)->level() > best_level))
+ {
+ best_distance = dist;
+ best_level = (*cell)->level();
+ best_cell = std::make_pair(*cell, p_cell);
+ }
+ }
- // The best distance is set to the
- // maximum allowable distance from
- // the unit cell; we assume a
- // max. deviation of 1e-10
- double best_distance = 1e-10;
- int best_level = -1;
- std::pair<cell_iterator, Point<spacedim> > best_cell;
+ Assert (best_cell.first.state() == IteratorState::valid,
+ ExcPointNotFound<dim>(p));
- // Find closest vertex and determine
- // all adjacent cells
- unsigned int vertex = find_closest_vertex(container, p);
+ return best_cell;
+ }
- std::vector<cell_iterator> adjacent_cells =
- find_cells_adjacent_to_vertex(container, vertex);
- typename std::vector<cell_iterator>::const_iterator
- cell = adjacent_cells.begin(),
- endc = adjacent_cells.end();
- for(; cell != endc; ++cell)
- {
- const Point<spacedim> p_cell
- = mapping[(*cell)->active_fe_index()].transform_real_to_unit_cell(*cell, p);
-
- // calculate the infinity norm of
- // the distance vector to the unit cell.
- const double dist = GeometryInfo<dim>::distance_to_unit_cell(p_cell);
-
- // We compare if the point is inside the
- // unit cell (or at least not too far
- // outside). If it is, it is also checked
- // that the cell has a more refined state
- if (dist < best_distance ||
- (dist == best_distance && (*cell)->level() > best_level))
- {
- best_distance = dist;
- best_level = (*cell)->level();
- best_cell = std::make_pair(*cell, p_cell);
- }
- }
+ template <int dim, int spacedim>
+ void
- Assert (best_cell.first.state() == IteratorState::valid,
- ExcPointNotFound<dim>(p));
+ get_face_connectivity_of_cells (const Triangulation<dim,spacedim> &triangulation,
+ SparsityPattern &cell_connectivity)
+ {
+ // as built in this function, we
+ // only consider face neighbors,
+ // which leads to a fixed number of
+ // entries per row (don't forget
+ // that each cell couples with
+ // itself, and that neighbors can
+ // be refined)
+ cell_connectivity.reinit (triangulation.n_active_cells(),
+ triangulation.n_active_cells(),
+ GeometryInfo<dim>::faces_per_cell
+ * GeometryInfo<dim>::max_children_per_face
+ +
+ 1);
+
+ // next we have to build a mapping from the
+ // list of cells to their indices. for
+ // this, use the user_index field
+ std::vector<unsigned int> saved_user_indices;
+ triangulation.save_user_indices (saved_user_indices);
+ unsigned int index = 0;
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell, ++index)
+ cell->set_user_index (index);
+
+ // next loop over all cells and
+ // their neighbors to build the
+ // sparsity pattern. note that it's
+ // a bit hard to enter all the
+ // connections when a neighbor has
+ // children since we would need to
+ // find out which of its children
+ // is adjacent to the current
+ // cell. this problem can be
+ // omitted if we only do something
+ // if the neighbor has no children
+ // -- in that case it is either on
+ // the same or a coarser level than
+ // we are. in return, we have to
+ // add entries in both directions
+ // for both cells
+ index = 0;
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell, ++index)
+ {
+ cell_connectivity.add (index, index);
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
+ if ((cell->at_boundary(f) == false)
+ &&
+ (cell->neighbor(f)->has_children() == false))
+ {
+ cell_connectivity.add (index,
+ cell->neighbor(f)->user_index());
+ cell_connectivity.add (cell->neighbor(f)->user_index(),
+ index);
+ }
+ }
- return best_cell;
-}
+ // now compress the so-built connectivity
+ // pattern and restore user indices. the
+ // const-cast is necessary since we treat
+ // the triangulation as constant (we here
+ // return it to its original state)
+ cell_connectivity.compress ();
+ const_cast<Triangulation<dim,spacedim>&>(triangulation)
+ .load_user_indices (saved_user_indices);
+ }
-template <int dim, int spacedim>
-void
-GridTools::
-get_face_connectivity_of_cells (const Triangulation<dim,spacedim> &triangulation,
- SparsityPattern &cell_connectivity)
-{
- // as built in this function, we
- // only consider face neighbors,
- // which leads to a fixed number of
- // entries per row (don't forget
- // that each cell couples with
- // itself, and that neighbors can
- // be refined)
- cell_connectivity.reinit (triangulation.n_active_cells(),
- triangulation.n_active_cells(),
- GeometryInfo<dim>::faces_per_cell
- * GeometryInfo<dim>::max_children_per_face
- +
- 1);
-
- // next we have to build a mapping from the
- // list of cells to their indices. for
- // this, use the user_index field
- std::vector<unsigned int> saved_user_indices;
- triangulation.save_user_indices (saved_user_indices);
- unsigned int index = 0;
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell, ++index)
- cell->set_user_index (index);
-
- // next loop over all cells and
- // their neighbors to build the
- // sparsity pattern. note that it's
- // a bit hard to enter all the
- // connections when a neighbor has
- // children since we would need to
- // find out which of its children
- // is adjacent to the current
- // cell. this problem can be
- // omitted if we only do something
- // if the neighbor has no children
- // -- in that case it is either on
- // the same or a coarser level than
- // we are. in return, we have to
- // add entries in both directions
- // for both cells
- index = 0;
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell, ++index)
- {
- cell_connectivity.add (index, index);
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell; ++f)
- if ((cell->at_boundary(f) == false)
- &&
- (cell->neighbor(f)->has_children() == false))
- {
- cell_connectivity.add (index,
- cell->neighbor(f)->user_index());
- cell_connectivity.add (cell->neighbor(f)->user_index(),
- index);
- }
- }
+ template <int dim, int spacedim>
+ void
- // now compress the so-built connectivity
- // pattern and restore user indices. the
- // const-cast is necessary since we treat
- // the triangulation as constant (we here
- // return it to its original state)
- cell_connectivity.compress ();
- const_cast<Triangulation<dim,spacedim>&>(triangulation)
- .load_user_indices (saved_user_indices);
-}
+ partition_triangulation (const unsigned int n_partitions,
+ Triangulation<dim,spacedim> &triangulation)
+ {
+ Assert ((dynamic_cast<parallel::distributed::Triangulation<dim,spacedim>*>
+ (&triangulation)
+ == 0),
+ ExcMessage ("Objects of type parallel::distributed::Triangulation "
+ "are already partitioned implicitly and can not be "
+ "partitioned again explicitly."));
+ Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
+
+ // check for an easy return
+ if (n_partitions == 1)
+ {
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell)
+ cell->set_subdomain_id (0);
+ return;
+ }
+ // we decompose the domain by first
+ // generating the connection graph of all
+ // cells with their neighbors, and then
+ // passing this graph off to METIS.
+ // finally defer to the other function for
+ // partitioning and assigning subdomain ids
+ SparsityPattern cell_connectivity;
+ get_face_connectivity_of_cells (triangulation, cell_connectivity);
+
+ partition_triangulation (n_partitions,
+ cell_connectivity,
+ triangulation);
+ }
-template <int dim, int spacedim>
-void
-GridTools::
-partition_triangulation (const unsigned int n_partitions,
- Triangulation<dim,spacedim> &triangulation)
-{
- Assert ((dynamic_cast<parallel::distributed::Triangulation<dim,spacedim>*>
- (&triangulation)
- == 0),
- ExcMessage ("Objects of type parallel::distributed::Triangulation "
- "are already partitioned implicitly and can not be "
- "partitioned again explicitly."));
- Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
-
- // check for an easy return
- if (n_partitions == 1)
- {
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell)
- cell->set_subdomain_id (0);
- return;
- }
- // we decompose the domain by first
- // generating the connection graph of all
- // cells with their neighbors, and then
- // passing this graph off to METIS.
- // finally defer to the other function for
- // partitioning and assigning subdomain ids
- SparsityPattern cell_connectivity;
- get_face_connectivity_of_cells (triangulation, cell_connectivity);
-
- partition_triangulation (n_partitions,
- cell_connectivity,
- triangulation);
-}
+ template <int dim, int spacedim>
+ void
+ partition_triangulation (const unsigned int n_partitions,
+ const SparsityPattern &cell_connection_graph,
+ Triangulation<dim,spacedim> &triangulation)
+ {
+ Assert ((dynamic_cast<parallel::distributed::Triangulation<dim,spacedim>*>
+ (&triangulation)
+ == 0),
+ ExcMessage ("Objects of type parallel::distributed::Triangulation "
+ "are already partitioned implicitly and can not be "
+ "partitioned again explicitly."));
+ Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
+ Assert (cell_connection_graph.n_rows() == triangulation.n_active_cells(),
+ ExcMessage ("Connectivity graph has wrong size"));
+ Assert (cell_connection_graph.n_cols() == triangulation.n_active_cells(),
+ ExcMessage ("Connectivity graph has wrong size"));
+
+ // check for an easy return
+ if (n_partitions == 1)
+ {
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell)
+ cell->set_subdomain_id (0);
+ return;
+ }
+ // partition this connection graph and get
+ // back a vector of indices, one per degree
+ // of freedom (which is associated with a
+ // cell)
+ std::vector<unsigned int> partition_indices (triangulation.n_active_cells());
+ SparsityTools::partition (cell_connection_graph, n_partitions, partition_indices);
+
+ // finally loop over all cells and set the
+ // subdomain ids
+ std::vector<unsigned int> dof_indices(1);
+ unsigned int index = 0;
+ for (typename Triangulation<dim,spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell != triangulation.end(); ++cell, ++index)
+ cell->set_subdomain_id (partition_indices[index]);
+ }
-template <int dim, int spacedim>
-void
-GridTools::
-partition_triangulation (const unsigned int n_partitions,
- const SparsityPattern &cell_connection_graph,
- Triangulation<dim,spacedim> &triangulation)
-{
- Assert ((dynamic_cast<parallel::distributed::Triangulation<dim,spacedim>*>
- (&triangulation)
- == 0),
- ExcMessage ("Objects of type parallel::distributed::Triangulation "
- "are already partitioned implicitly and can not be "
- "partitioned again explicitly."));
- Assert (n_partitions > 0, ExcInvalidNumberOfPartitions(n_partitions));
- Assert (cell_connection_graph.n_rows() == triangulation.n_active_cells(),
- ExcMessage ("Connectivity graph has wrong size"));
- Assert (cell_connection_graph.n_cols() == triangulation.n_active_cells(),
- ExcMessage ("Connectivity graph has wrong size"));
-
- // check for an easy return
- if (n_partitions == 1)
- {
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell)
- cell->set_subdomain_id (0);
- return;
- }
- // partition this connection graph and get
- // back a vector of indices, one per degree
- // of freedom (which is associated with a
- // cell)
- std::vector<unsigned int> partition_indices (triangulation.n_active_cells());
- SparsityTools::partition (cell_connection_graph, n_partitions, partition_indices);
-
- // finally loop over all cells and set the
- // subdomain ids
- std::vector<unsigned int> dof_indices(1);
- unsigned int index = 0;
- for (typename Triangulation<dim,spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell != triangulation.end(); ++cell, ++index)
- cell->set_subdomain_id (partition_indices[index]);
-}
+ template <int dim, int spacedim>
+ void
+ get_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
+ std::vector<types::subdomain_id_t> &subdomain)
+ {
+ Assert (subdomain.size() == triangulation.n_active_cells(),
+ ExcDimensionMismatch (subdomain.size(),
+ triangulation.n_active_cells()));
+ unsigned int index = 0;
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell!=triangulation.end(); ++cell, ++index)
+ subdomain[index] = cell->subdomain_id();
+
+ Assert (index == subdomain.size(), ExcInternalError());
+ }
-template <int dim, int spacedim>
-void
-GridTools::
-get_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
- std::vector<types::subdomain_id_t> &subdomain)
-{
- Assert (subdomain.size() == triangulation.n_active_cells(),
- ExcDimensionMismatch (subdomain.size(),
- triangulation.n_active_cells()));
- unsigned int index = 0;
- for (typename Triangulation<dim, spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell!=triangulation.end(); ++cell, ++index)
- subdomain[index] = cell->subdomain_id();
-
- Assert (index == subdomain.size(), ExcInternalError());
-}
+ template <int dim, int spacedim>
+ unsigned int
-template <int dim, int spacedim>
-unsigned int
-GridTools::
-count_cells_with_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
- const types::subdomain_id_t subdomain)
-{
- unsigned int count = 0;
- for (typename Triangulation<dim, spacedim>::active_cell_iterator
- cell = triangulation.begin_active();
- cell!=triangulation.end(); ++cell)
- if (cell->subdomain_id() == subdomain)
- ++count;
-
- return count;
-}
+ count_cells_with_subdomain_association (const Triangulation<dim, spacedim> &triangulation,
+ const types::subdomain_id_t subdomain)
+ {
+ unsigned int count = 0;
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator
+ cell = triangulation.begin_active();
+ cell!=triangulation.end(); ++cell)
+ if (cell->subdomain_id() == subdomain)
+ ++count;
+
+ return count;
+ }
-template <typename Container>
-std::list<std::pair<typename Container::cell_iterator,
- typename Container::cell_iterator> >
-GridTools::get_finest_common_cells (const Container &mesh_1,
- const Container &mesh_2)
-{
- Assert (have_same_coarse_mesh (mesh_1, mesh_2),
- ExcMessage ("The two containers must be represent triangulations that "
- "have the same coarse meshes"));
-
- // the algorithm goes as follows:
- // first, we fill a list with pairs
- // of iterators common to the two
- // meshes on the coarsest
- // level. then we traverse the
- // list; each time, we find a pair
- // of iterators for which both
- // correspond to non-active cells,
- // we delete this item and push the
- // pairs of iterators to their
- // children to the back. if these
- // again both correspond to
- // non-active cells, we will get to
- // the later on for further
- // consideration
- typedef
- std::list<std::pair<typename Container::cell_iterator,
- typename Container::cell_iterator> >
- CellList;
-
- CellList cell_list;
-
- // first push the coarse level cells
- typename Container::cell_iterator
- cell_1 = mesh_1.begin(0),
- cell_2 = mesh_2.begin(0);
- for (; cell_1 != mesh_1.end(0); ++cell_1, ++cell_2)
- cell_list.push_back (std::make_pair (cell_1, cell_2));
-
- // then traverse list as described
- // above
- typename CellList::iterator cell_pair = cell_list.begin();
- while (cell_pair != cell_list.end())
- {
- // if both cells in this pair
- // have children, then erase
- // this element and push their
- // children instead
- if (cell_pair->first->has_children()
- &&
- cell_pair->second->has_children())
- {
- Assert(cell_pair->first->refinement_case()==
- cell_pair->second->refinement_case(), ExcNotImplemented());
- for (unsigned int c=0; c<cell_pair->first->n_children(); ++c)
- cell_list.push_back (std::make_pair (cell_pair->first->child(c),
- cell_pair->second->child(c)));
-
- // erasing an iterator
- // keeps other iterators
- // valid, so already
- // advance the present
- // iterator by one and then
- // delete the element we've
- // visited before
- const typename CellList::iterator previous_cell_pair = cell_pair;
- ++cell_pair;
-
- cell_list.erase (previous_cell_pair);
- }
- else
- // both cells are active, do
- // nothing
- ++cell_pair;
- }
+ template <typename Container>
+ std::list<std::pair<typename Container::cell_iterator,
+ typename Container::cell_iterator> >
+ get_finest_common_cells (const Container &mesh_1,
+ const Container &mesh_2)
+ {
+ Assert (have_same_coarse_mesh (mesh_1, mesh_2),
+ ExcMessage ("The two containers must be represent triangulations that "
+ "have the same coarse meshes"));
+
+ // the algorithm goes as follows:
+ // first, we fill a list with pairs
+ // of iterators common to the two
+ // meshes on the coarsest
+ // level. then we traverse the
+ // list; each time, we find a pair
+ // of iterators for which both
+ // correspond to non-active cells,
+ // we delete this item and push the
+ // pairs of iterators to their
+ // children to the back. if these
+ // again both correspond to
+ // non-active cells, we will get to
+ // the later on for further
+ // consideration
+ typedef
+ std::list<std::pair<typename Container::cell_iterator,
+ typename Container::cell_iterator> >
+ CellList;
+
+ CellList cell_list;
+
+ // first push the coarse level cells
+ typename Container::cell_iterator
+ cell_1 = mesh_1.begin(0),
+ cell_2 = mesh_2.begin(0);
+ for (; cell_1 != mesh_1.end(0); ++cell_1, ++cell_2)
+ cell_list.push_back (std::make_pair (cell_1, cell_2));
+
+ // then traverse list as described
+ // above
+ typename CellList::iterator cell_pair = cell_list.begin();
+ while (cell_pair != cell_list.end())
+ {
+ // if both cells in this pair
+ // have children, then erase
+ // this element and push their
+ // children instead
+ if (cell_pair->first->has_children()
+ &&
+ cell_pair->second->has_children())
+ {
+ Assert(cell_pair->first->refinement_case()==
+ cell_pair->second->refinement_case(), ExcNotImplemented());
+ for (unsigned int c=0; c<cell_pair->first->n_children(); ++c)
+ cell_list.push_back (std::make_pair (cell_pair->first->child(c),
+ cell_pair->second->child(c)));
+
+ // erasing an iterator
+ // keeps other iterators
+ // valid, so already
+ // advance the present
+ // iterator by one and then
+ // delete the element we've
+ // visited before
+ const typename CellList::iterator previous_cell_pair = cell_pair;
+ ++cell_pair;
+
+ cell_list.erase (previous_cell_pair);
+ }
+ else
+ // both cells are active, do
+ // nothing
+ ++cell_pair;
+ }
- // just to make sure everything is ok,
- // validate that all pairs have at least one
- // active iterator or have different
- // refinement_cases
- for (cell_pair = cell_list.begin(); cell_pair != cell_list.end(); ++cell_pair)
- Assert (cell_pair->first->active()
- ||
- cell_pair->second->active()
- ||
- (cell_pair->first->refinement_case()
- != cell_pair->second->refinement_case()),
- ExcInternalError());
-
- return cell_list;
-}
+ // just to make sure everything is ok,
+ // validate that all pairs have at least one
+ // active iterator or have different
+ // refinement_cases
+ for (cell_pair = cell_list.begin(); cell_pair != cell_list.end(); ++cell_pair)
+ Assert (cell_pair->first->active()
+ ||
+ cell_pair->second->active()
+ ||
+ (cell_pair->first->refinement_case()
+ != cell_pair->second->refinement_case()),
+ ExcInternalError());
+
+ return cell_list;
+ }
-template <int dim, int spacedim>
-bool
-GridTools::have_same_coarse_mesh (const Triangulation<dim, spacedim> &mesh_1,
- const Triangulation<dim, spacedim> &mesh_2)
-{
- // make sure the two meshes have
- // the same number of coarse cells
- if (mesh_1.n_cells (0) != mesh_2.n_cells (0))
- return false;
-
- // if so, also make sure they have
- // the same vertices on the cells
- // of the coarse mesh
- typename Triangulation<dim, spacedim>::cell_iterator
- cell_1 = mesh_1.begin(0),
- cell_2 = mesh_2.begin(0),
- endc = mesh_1.end(0);
- for (; cell_1!=endc; ++cell_1, ++cell_2)
- for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
- if (cell_1->vertex(v) != cell_2->vertex(v))
- return false;
-
- // if we've gotten through all
- // this, then the meshes really
- // seem to have a common coarse
- // mesh
- return true;
-}
+ template <int dim, int spacedim>
+ bool
+ have_same_coarse_mesh (const Triangulation<dim, spacedim> &mesh_1,
+ const Triangulation<dim, spacedim> &mesh_2)
+ {
+ // make sure the two meshes have
+ // the same number of coarse cells
+ if (mesh_1.n_cells (0) != mesh_2.n_cells (0))
+ return false;
+
+ // if so, also make sure they have
+ // the same vertices on the cells
+ // of the coarse mesh
+ typename Triangulation<dim, spacedim>::cell_iterator
+ cell_1 = mesh_1.begin(0),
+ cell_2 = mesh_2.begin(0),
+ endc = mesh_1.end(0);
+ for (; cell_1!=endc; ++cell_1, ++cell_2)
+ for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_cell; ++v)
+ if (cell_1->vertex(v) != cell_2->vertex(v))
+ return false;
+
+ // if we've gotten through all
+ // this, then the meshes really
+ // seem to have a common coarse
+ // mesh
+ return true;
+ }
-template <typename Container>
-bool
-GridTools::have_same_coarse_mesh (const Container &mesh_1,
- const Container &mesh_2)
-{
- return have_same_coarse_mesh (mesh_1.get_tria(),
- mesh_2.get_tria());
-}
+ template <typename Container>
+ bool
+ have_same_coarse_mesh (const Container &mesh_1,
+ const Container &mesh_2)
+ {
+ return have_same_coarse_mesh (mesh_1.get_tria(),
+ mesh_2.get_tria());
+ }
-template <int dim, int spacedim>
-double
-GridTools::minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation)
-{
- double min_diameter = triangulation.begin_active()->diameter();
- for (typename Triangulation<dim, spacedim>::active_cell_iterator
- cell = triangulation.begin_active(); cell != triangulation.end();
- ++cell)
- min_diameter = std::min (min_diameter,
- cell->diameter());
- return min_diameter;
-}
+ template <int dim, int spacedim>
+ double
+ minimal_cell_diameter (const Triangulation<dim, spacedim> &triangulation)
+ {
+ double min_diameter = triangulation.begin_active()->diameter();
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(); cell != triangulation.end();
+ ++cell)
+ min_diameter = std::min (min_diameter,
+ cell->diameter());
+ return min_diameter;
+ }
-template <int dim, int spacedim>
-double
-GridTools::maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation)
-{
- double max_diameter = triangulation.begin_active()->diameter();
- for (typename Triangulation<dim, spacedim>::active_cell_iterator
- cell = triangulation.begin_active(); cell != triangulation.end();
- ++cell)
- max_diameter = std::max (max_diameter,
- cell->diameter());
- return max_diameter;
-}
+ template <int dim, int spacedim>
+ double
+ maximal_cell_diameter (const Triangulation<dim, spacedim> &triangulation)
+ {
+ double max_diameter = triangulation.begin_active()->diameter();
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator
+ cell = triangulation.begin_active(); cell != triangulation.end();
+ ++cell)
+ max_diameter = std::max (max_diameter,
+ cell->diameter());
+ return max_diameter;
+ }
-template <int dim, int spacedim>
-void
-GridTools::create_union_triangulation (const Triangulation<dim, spacedim> &triangulation_1,
- const Triangulation<dim, spacedim> &triangulation_2,
- Triangulation<dim, spacedim> &result)
-{
- Assert (have_same_coarse_mesh (triangulation_1, triangulation_2),
- ExcMessage ("The two input triangulations are not derived from "
- "the same coarse mesh as required."));
-
- // first copy triangulation_1, and
- // then do as many iterations as
- // there are levels in
- // triangulation_2 to refine
- // additional cells. since this is
- // the maximum number of
- // refinements to get from the
- // coarse grid to triangulation_2,
- // it is clear that this is also
- // the maximum number of
- // refinements to get from any cell
- // on triangulation_1 to
- // triangulation_2
- result.clear ();
- result.copy_triangulation (triangulation_1);
- for (unsigned int iteration=0; iteration<triangulation_2.n_levels();
- ++iteration)
- {
- InterGridMap<Triangulation<dim, spacedim> > intergrid_map;
- intergrid_map.make_mapping (result, triangulation_2);
-
- bool any_cell_flagged = false;
- for (typename Triangulation<dim, spacedim>::active_cell_iterator
- result_cell = result.begin_active();
- result_cell != result.end(); ++result_cell)
- if (intergrid_map[result_cell]->has_children())
- {
- any_cell_flagged = true;
- result_cell->set_refine_flag ();
- }
+ template <int dim, int spacedim>
+ void
+ create_union_triangulation (const Triangulation<dim, spacedim> &triangulation_1,
+ const Triangulation<dim, spacedim> &triangulation_2,
+ Triangulation<dim, spacedim> &result)
+ {
+ Assert (have_same_coarse_mesh (triangulation_1, triangulation_2),
+ ExcMessage ("The two input triangulations are not derived from "
+ "the same coarse mesh as required."));
+
+ // first copy triangulation_1, and
+ // then do as many iterations as
+ // there are levels in
+ // triangulation_2 to refine
+ // additional cells. since this is
+ // the maximum number of
+ // refinements to get from the
+ // coarse grid to triangulation_2,
+ // it is clear that this is also
+ // the maximum number of
+ // refinements to get from any cell
+ // on triangulation_1 to
+ // triangulation_2
+ result.clear ();
+ result.copy_triangulation (triangulation_1);
+ for (unsigned int iteration=0; iteration<triangulation_2.n_levels();
+ ++iteration)
+ {
+ InterGridMap<Triangulation<dim, spacedim> > intergrid_map;
+ intergrid_map.make_mapping (result, triangulation_2);
+
+ bool any_cell_flagged = false;
+ for (typename Triangulation<dim, spacedim>::active_cell_iterator
+ result_cell = result.begin_active();
+ result_cell != result.end(); ++result_cell)
+ if (intergrid_map[result_cell]->has_children())
+ {
+ any_cell_flagged = true;
+ result_cell->set_refine_flag ();
+ }
- if (any_cell_flagged == false)
- break;
- else
- result.execute_coarsening_and_refinement();
- }
-}
+ if (any_cell_flagged == false)
+ break;
+ else
+ result.execute_coarsening_and_refinement();
+ }
+ }
-namespace internal
-{
- namespace GridTools
+ namespace internal
{
namespace FixUpDistortedChildCells
{
Point<Iterator::AccessorType::space_dimension>
get_face_midpoint (const Iterator &object,
const unsigned int f,
- internal::int2type<1>)
+ dealii::internal::int2type<1>)
{
return object->vertex(f);
}
Point<Iterator::AccessorType::space_dimension>
get_face_midpoint (const Iterator &object,
const unsigned int f,
- internal::int2type<2>)
+ dealii::internal::int2type<2>)
{
return object->line(f)->center();
}
Point<Iterator::AccessorType::space_dimension>
get_face_midpoint (const Iterator &object,
const unsigned int f,
- internal::int2type<3>)
+ dealii::internal::int2type<3>)
{
return object->face(f)->center();
}
diameter = std::min (diameter,
get_face_midpoint
(object, f,
- internal::int2type<structdim>())
+ dealii::internal::int2type<structdim>())
.distance (get_face_midpoint
(object,
e,
- internal::int2type<structdim>())));
+ dealii::internal::int2type<structdim>())));
return diameter;
}
const bool respect_manifold)
{
const Boundary<Iterator::AccessorType::dimension,
- Iterator::AccessorType::space_dimension>
+ Iterator::AccessorType::space_dimension>
*manifold = (respect_manifold ?
&object->get_boundary() :
0);
}
while (iteration < 20);
-// std::cout << "# iterations=" << iteration << std::endl;
-
-
// verify that the new
// location is indeed better
// than the one before. check
child_alternating_forms[c][i] *
parent_alternating_forms[j]);
- // for the new minimum value,
- // replace mid-object
- // vertex. note that for child
- // i, the mid-object vertex
- // happens to have the number
- // max_children_per_cell-i
+ // for the new minimum value,
+ // replace mid-object
+ // vertex. note that for child
+ // i, the mid-object vertex
+ // happens to have the number
+ // max_children_per_cell-i
for (unsigned int c=0; c<object->n_children(); ++c)
child_vertices[c][GeometryInfo<structdim>::max_children_per_cell-c-1]
= object_mid_point;
// mid-points
template <int structdim, int spacedim>
void fix_up_faces (const typename dealii::Triangulation<structdim,spacedim>::cell_iterator &cell,
- internal::int2type<structdim>,
- internal::int2type<spacedim>)
+ dealii::internal::int2type<structdim>,
+ dealii::internal::int2type<spacedim>)
{
// see if we first can fix up
// some of the faces of this
template <int spacedim>
void fix_up_faces (const typename dealii::Triangulation<1,spacedim>::cell_iterator &,
- internal::int2type<1>,
- internal::int2type<spacedim>)
+ dealii::internal::int2type<1>,
+ dealii::internal::int2type<spacedim>)
{
// nothing to do for the faces of
// cells in 1d
void fix_up_faces (const dealii::Triangulation<1,1>::cell_iterator &,
- internal::int2type<1>,
- internal::int2type<1>)
+ dealii::internal::int2type<1>,
+ dealii::internal::int2type<1>)
{
// nothing to do for the faces of
// cells in 1d
}
}
}
-}
-template <int dim, int spacedim>
-typename Triangulation<dim,spacedim>::DistortedCellList
-GridTools::
-fix_up_distorted_child_cells (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
- Triangulation<dim,spacedim> &/*triangulation*/)
-{
- typename Triangulation<dim,spacedim>::DistortedCellList unfixable_subset;
+ template <int dim, int spacedim>
+ typename Triangulation<dim,spacedim>::DistortedCellList
- // loop over all cells that we have
- // to fix up
- for (typename std::list<typename Triangulation<dim,spacedim>::cell_iterator>::const_iterator
- cell_ptr = distorted_cells.distorted_cells.begin();
- cell_ptr != distorted_cells.distorted_cells.end(); ++cell_ptr)
- {
- const typename Triangulation<dim,spacedim>::cell_iterator
- cell = *cell_ptr;
-
- internal::GridTools::FixUpDistortedChildCells
- ::fix_up_faces (cell,
- internal::int2type<dim>(),
- internal::int2type<spacedim>());
-
- // fix up the object. we need to
- // respect the manifold if the cell is
- // embedded in a higher dimensional
- // space; otherwise, like a hex in 3d,
- // every point within the cell interior
- // is fair game
- if (! internal::GridTools::FixUpDistortedChildCells::fix_up_object (cell,
- (dim < spacedim)))
- unfixable_subset.distorted_cells.push_back (cell);
- }
+ fix_up_distorted_child_cells (const typename Triangulation<dim,spacedim>::DistortedCellList &distorted_cells,
+ Triangulation<dim,spacedim> &/*triangulation*/)
+ {
+ typename Triangulation<dim,spacedim>::DistortedCellList unfixable_subset;
- return unfixable_subset;
-}
+ // loop over all cells that we have
+ // to fix up
+ for (typename std::list<typename Triangulation<dim,spacedim>::cell_iterator>::const_iterator
+ cell_ptr = distorted_cells.distorted_cells.begin();
+ cell_ptr != distorted_cells.distorted_cells.end(); ++cell_ptr)
+ {
+ const typename Triangulation<dim,spacedim>::cell_iterator
+ cell = *cell_ptr;
+
+ internal::FixUpDistortedChildCells
+ ::fix_up_faces (cell,
+ dealii::internal::int2type<dim>(),
+ dealii::internal::int2type<spacedim>());
+
+ // fix up the object. we need to
+ // respect the manifold if the cell is
+ // embedded in a higher dimensional
+ // space; otherwise, like a hex in 3d,
+ // every point within the cell interior
+ // is fair game
+ if (! internal::FixUpDistortedChildCells::fix_up_object (cell,
+ (dim < spacedim)))
+ unfixable_subset.distorted_cells.push_back (cell);
+ }
+
+ return unfixable_subset;
+ }
-template <template <int,int> class Container, int dim, int spacedim>
-std::map<typename Container<dim-1,spacedim>::cell_iterator,
- typename Container<dim,spacedim>::face_iterator>
-GridTools::extract_boundary_mesh (const Container<dim,spacedim> &volume_mesh,
- Container<dim-1,spacedim> &surface_mesh,
- const std::set<unsigned char> &boundary_ids)
-{
+ template <template <int,int> class Container, int dim, int spacedim>
+ std::map<typename Container<dim-1,spacedim>::cell_iterator,
+ typename Container<dim,spacedim>::face_iterator>
+ extract_boundary_mesh (const Container<dim,spacedim> &volume_mesh,
+ Container<dim-1,spacedim> &surface_mesh,
+ const std::set<unsigned char> &boundary_ids)
+ {
// Assumption:
// We are relying below on the fact that Triangulation::create_triangulation(...) will keep the order
// pass by CellData and that it will not reorder the vertices.
- std::map<typename Container<dim-1,spacedim>::cell_iterator,
- typename Container<dim,spacedim>::face_iterator>
- surface_to_volume_mapping;
+ std::map<typename Container<dim-1,spacedim>::cell_iterator,
+ typename Container<dim,spacedim>::face_iterator>
+ surface_to_volume_mapping;
- const unsigned int boundary_dim = dim-1; //dimension of the boundary mesh
+ const unsigned int boundary_dim = dim-1; //dimension of the boundary mesh
- // First create surface mesh and mapping from only level(0) cells of volume_mesh
+ // First create surface mesh and mapping
+ // from only level(0) cells of volume_mesh
+ std::vector<typename Container<dim,spacedim>::face_iterator>
+ mapping; // temporary map for level==0
- std::vector<typename Container<dim,spacedim>::face_iterator>
- mapping; // temporary map for level==0
+ std::vector< bool > touched (get_tria(volume_mesh).n_vertices(), false);
+ std::vector< CellData< boundary_dim > > cells;
+ std::vector< Point<spacedim> > vertices;
- std::vector< bool > touched (get_tria(volume_mesh).n_vertices(), false);
- std::vector< CellData< boundary_dim > > cells;
- std::vector< Point<spacedim> > vertices;
+ std::map<unsigned int,unsigned int> map_vert_index; //volume vertex indices to surf ones
- std::map<unsigned int,unsigned int> map_vert_index; //volume vertex indices to surf ones
+ unsigned int v_index;
+ CellData< boundary_dim > c_data;
- unsigned int v_index;
- CellData< boundary_dim > c_data;
+ for (typename Container<dim,spacedim>::cell_iterator
+ cell = volume_mesh.begin(0);
+ cell != volume_mesh.end(0);
+ ++cell)
+ for (unsigned int i=0; i < GeometryInfo<dim>::faces_per_cell; ++i)
+ {
+ const typename Container<dim,spacedim>::face_iterator
+ face = cell->face(i);
- for (typename Container<dim,spacedim>::cell_iterator
- cell = volume_mesh.begin(0);
- cell != volume_mesh.end(0);
- ++cell)
- for (unsigned int i=0; i < GeometryInfo<dim>::faces_per_cell; ++i)
- {
- const typename Container<dim,spacedim>::face_iterator
- face = cell->face(i);
+ if ( face->at_boundary()
+ &&
+ (boundary_ids.empty() ||
+ ( boundary_ids.find(face->boundary_indicator()) != boundary_ids.end())) )
+ {
+ for (unsigned int j=0;
+ j<GeometryInfo<boundary_dim>::vertices_per_cell; ++j)
+ {
+ v_index = face->vertex_index(j);
- if ( face->at_boundary()
- &&
- (boundary_ids.empty() ||
- ( boundary_ids.find(face->boundary_indicator()) != boundary_ids.end())) )
- {
- for (unsigned int j=0;
- j<GeometryInfo<boundary_dim>::vertices_per_cell; ++j)
- {
- v_index = face->vertex_index(j);
+ if ( !touched[v_index] )
+ {
+ vertices.push_back(face->vertex(j));
+ map_vert_index[v_index] = vertices.size() - 1;
+ touched[v_index] = true;
+ }
- if ( !touched[v_index] )
- {
- vertices.push_back(face->vertex(j));
- map_vert_index[v_index] = vertices.size() - 1;
- touched[v_index] = true;
- }
+ c_data.vertices[j] = map_vert_index[v_index];
+ c_data.material_id = face->boundary_indicator();
+ }
- c_data.vertices[j] = map_vert_index[v_index];
- c_data.material_id = face->boundary_indicator();
- }
+ cells.push_back(c_data);
+ mapping.push_back(face);
+ }
+ }
- cells.push_back(c_data);
- mapping.push_back(face);
- }
- }
+ // create level 0 surface triangulation
+ Assert (cells.size() > 0, ExcMessage ("No boundary faces selected"));
+ const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
+ .create_triangulation (vertices, cells, SubCellData());
- // create level 0 surface triangulation
- Assert (cells.size() > 0, ExcMessage ("No boundary faces selected"));
- const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
- .create_triangulation (vertices, cells, SubCellData());
+ // Make the actual mapping
+ for (typename Container<dim-1,spacedim>::active_cell_iterator
+ cell = surface_mesh.begin(0);
+ cell!=surface_mesh.end(0); ++cell)
+ surface_to_volume_mapping[cell] = mapping.at(cell->index());
- // Make the actual mapping
- for (typename Container<dim-1,spacedim>::active_cell_iterator
- cell = surface_mesh.begin(0);
- cell!=surface_mesh.end(0); ++cell)
- surface_to_volume_mapping[cell] = mapping.at(cell->index());
+ do
+ {
+ bool changed = false;
+ typename Container<dim-1,spacedim>::active_cell_iterator
+ cell = surface_mesh.begin_active(),
+ endc = surface_mesh.end();
- do
- {
- bool changed = false;
- typename Container<dim-1,spacedim>::active_cell_iterator
- cell = surface_mesh.begin_active(),
- endc = surface_mesh.end();
+ for (; cell!=endc; ++cell)
+ if (surface_to_volume_mapping[cell]->has_children() == true )
+ {
+ cell->set_refine_flag ();
+ changed = true;
+ }
- for (; cell!=endc; ++cell)
- if (surface_to_volume_mapping[cell]->has_children() == true )
+ if (changed)
{
- cell->set_refine_flag ();
- changed = true;
+ const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
+ .execute_coarsening_and_refinement();
+
+ typename Container<dim-1,spacedim>::cell_iterator
+ cell = surface_mesh.begin(),
+ endc = surface_mesh.end();
+ for (; cell!=endc; ++cell)
+ for (unsigned int c=0; c<cell->n_children(); c++)
+ if (surface_to_volume_mapping.find(cell->child(c)) == surface_to_volume_mapping.end())
+ surface_to_volume_mapping[cell->child(c)]
+ = surface_to_volume_mapping[cell]->child(c);
}
+ else
+ break;
+ }
+ while (true);
- if (changed)
- {
- const_cast<Triangulation<dim-1,spacedim>&>(get_tria(surface_mesh))
- .execute_coarsening_and_refinement();
-
- typename Container<dim-1,spacedim>::cell_iterator
- cell = surface_mesh.begin(),
- endc = surface_mesh.end();
- for (; cell!=endc; ++cell)
- for (unsigned int c=0; c<cell->n_children(); c++)
- if (surface_to_volume_mapping.find(cell->child(c)) == surface_to_volume_mapping.end())
- surface_to_volume_mapping[cell->child(c)]
- = surface_to_volume_mapping[cell]->child(c);
- }
- else
- break;
- }
- while (true);
+ return surface_to_volume_mapping;
+ }
- return surface_to_volume_mapping;
}
+
// explicit instantiations
#include "grid_tools.inst"
for (X : TRIANGULATION_AND_DOFHANDLERS; deal_II_dimension : DIMENSIONS)
{
+ namespace GridTools \{
+
template
unsigned int
- GridTools::find_closest_vertex (const X &,
+ find_closest_vertex (const X &,
const Point<deal_II_dimension> &);
template
std::vector<X::active_cell_iterator>
- GridTools::find_cells_adjacent_to_vertex(const X &,
+ find_cells_adjacent_to_vertex(const X &,
const unsigned int);
template
X::active_cell_iterator
- GridTools::find_active_cell_around_point (const X &,
+ find_active_cell_around_point (const X &,
const Point<deal_II_dimension> &p);
template
std::pair<X::active_cell_iterator, Point<deal_II_dimension> >
- GridTools::find_active_cell_around_point (const Mapping<deal_II_dimension> &,
+ find_active_cell_around_point (const Mapping<deal_II_dimension> &,
const X &,
const Point<deal_II_dimension> &);
template
std::list<std::pair<X::cell_iterator, X::cell_iterator> >
- GridTools::
+
get_finest_common_cells (const X &mesh_1,
const X &mesh_2);
template
bool
- GridTools::have_same_coarse_mesh (const X &mesh_1,
+ have_same_coarse_mesh (const X &mesh_1,
const X &mesh_2);
+
+ \}
}
for (deal_II_dimension : DIMENSIONS)
{
+ namespace GridTools \{
+
template
double
- GridTools::diameter<deal_II_dimension> (const Triangulation<deal_II_dimension> &);
+ diameter<deal_II_dimension> (const Triangulation<deal_II_dimension> &);
#if deal_II_dimension < 3
template
double
- GridTools::diameter<deal_II_dimension, deal_II_dimension+1> (const Triangulation<deal_II_dimension, deal_II_dimension+1> &);
+ diameter<deal_II_dimension, deal_II_dimension+1> (const Triangulation<deal_II_dimension, deal_II_dimension+1> &);
#endif
template
double
- GridTools::volume<deal_II_dimension> (const Triangulation<deal_II_dimension> &,
+ volume<deal_II_dimension> (const Triangulation<deal_II_dimension> &,
const Mapping<deal_II_dimension> &);
#if deal_II_dimension < 3
template
double
- GridTools::volume<deal_II_dimension, deal_II_dimension+1> (const Triangulation<deal_II_dimension, deal_II_dimension+1> &,
+ volume<deal_II_dimension, deal_II_dimension+1> (const Triangulation<deal_II_dimension, deal_II_dimension+1> &,
const Mapping<deal_II_dimension, deal_II_dimension+1> &);
#endif
template
- void GridTools::delete_unused_vertices (std::vector<Point<deal_II_dimension> > &,
+ void delete_unused_vertices (std::vector<Point<deal_II_dimension> > &,
std::vector<CellData<deal_II_dimension> > &,
SubCellData &);
template
- void GridTools::delete_duplicated_vertices (std::vector<Point<deal_II_dimension> > &,
+ void delete_duplicated_vertices (std::vector<Point<deal_II_dimension> > &,
std::vector<CellData<deal_II_dimension> > &,
SubCellData &,
std::vector<unsigned int> &,
double);
template
- void GridTools::shift<deal_II_dimension> (const Point<deal_II_dimension> &,
+ void shift<deal_II_dimension> (const Point<deal_II_dimension> &,
Triangulation<deal_II_dimension> &);
template
- void GridTools::scale<deal_II_dimension> (const double,
+ void scale<deal_II_dimension> (const double,
Triangulation<deal_II_dimension> &);
template
std::pair<hp::DoFHandler<deal_II_dimension>::active_cell_iterator, Point<deal_II_dimension> >
- GridTools::find_active_cell_around_point (const hp::MappingCollection<deal_II_dimension> &,
+ find_active_cell_around_point (const hp::MappingCollection<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const Point<deal_II_dimension> &);
template
void
- GridTools::
+
get_face_connectivity_of_cells (const Triangulation<deal_II_dimension> &triangulation,
SparsityPattern &cell_connectivity);
#if deal_II_dimension < 3
template
void
- GridTools::
+
get_face_connectivity_of_cells (const Triangulation<deal_II_dimension,deal_II_dimension+1> &triangulation,
SparsityPattern &cell_connectivity);
#endif
template
void
- GridTools::partition_triangulation (const unsigned int,
+ partition_triangulation (const unsigned int,
Triangulation<deal_II_dimension> &);
template
void
- GridTools::partition_triangulation (const unsigned int,
+ partition_triangulation (const unsigned int,
const SparsityPattern &,
Triangulation<deal_II_dimension> &);
#if deal_II_dimension < 3
template
void
- GridTools::partition_triangulation (const unsigned int,
+ partition_triangulation (const unsigned int,
Triangulation<deal_II_dimension,deal_II_dimension+1> &);
template
void
- GridTools::partition_triangulation (const unsigned int,
+ partition_triangulation (const unsigned int,
const SparsityPattern &,
Triangulation<deal_II_dimension,deal_II_dimension+1> &);
#endif
template
void
- GridTools::
+
get_subdomain_association (const Triangulation<deal_II_dimension> &,
std::vector<types::subdomain_id_t> &);
template
unsigned int
- GridTools::
+
count_cells_with_subdomain_association (const Triangulation<deal_II_dimension> &,
const types::subdomain_id_t);
template
double
- GridTools::minimal_cell_diameter (const Triangulation<deal_II_dimension> &triangulation);
+ minimal_cell_diameter (const Triangulation<deal_II_dimension> &triangulation);
template
double
- GridTools::maximal_cell_diameter (const Triangulation<deal_II_dimension> &triangulation);
+ maximal_cell_diameter (const Triangulation<deal_II_dimension> &triangulation);
template
void
- GridTools::create_union_triangulation (const Triangulation<deal_II_dimension> &triangulation_1,
+ create_union_triangulation (const Triangulation<deal_II_dimension> &triangulation_1,
const Triangulation<deal_II_dimension> &triangulation_2,
Triangulation<deal_II_dimension> &result);
template
Triangulation<deal_II_dimension,deal_II_dimension>::DistortedCellList
- GridTools::
+
fix_up_distorted_child_cells (const Triangulation<deal_II_dimension,deal_II_dimension>::DistortedCellList &distorted_cells,
Triangulation<deal_II_dimension,deal_II_dimension> &triangulation);
#if deal_II_dimension != 3
template
- void GridTools::delete_unused_vertices (std::vector<Point<deal_II_dimension+1> > &,
+ void delete_unused_vertices (std::vector<Point<deal_II_dimension+1> > &,
std::vector<CellData<deal_II_dimension> > &,
SubCellData &);
template
- void GridTools::delete_duplicated_vertices (std::vector<Point<deal_II_dimension+1> > &,
+ void delete_duplicated_vertices (std::vector<Point<deal_II_dimension+1> > &,
std::vector<CellData<deal_II_dimension> > &,
SubCellData &,
std::vector<unsigned int> &,
double);
template
- void GridTools::shift<deal_II_dimension, deal_II_dimension+1> (const Point<deal_II_dimension+1> &,
+ void shift<deal_II_dimension, deal_II_dimension+1> (const Point<deal_II_dimension+1> &,
Triangulation<deal_II_dimension, deal_II_dimension+1> &);
template
- void GridTools::scale<deal_II_dimension, deal_II_dimension+1> (const double,
+ void scale<deal_II_dimension, deal_II_dimension+1> (const double,
Triangulation<deal_II_dimension, deal_II_dimension+1> &);
template
std::list<std::pair<Triangulation<deal_II_dimension,deal_II_dimension+1>::cell_iterator, Triangulation<deal_II_dimension,deal_II_dimension+1>::cell_iterator> >
- GridTools::
+
get_finest_common_cells (const Triangulation<deal_II_dimension,deal_II_dimension+1> &mesh_1,
const Triangulation<deal_II_dimension,deal_II_dimension+1> &mesh_2);
template
std::list<std::pair<DoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator, DoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator> >
- GridTools::
+
get_finest_common_cells (const DoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_1,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_2);
template
std::list<std::pair<hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator, hp::DoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator> >
- GridTools::
+
get_finest_common_cells (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_1,
const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_2);
template
std::list<std::pair<MGDoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator, MGDoFHandler<deal_II_dimension,deal_II_dimension+1>::cell_iterator> >
- GridTools::
+
get_finest_common_cells (const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_1,
const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &mesh_2);
-
-
#endif
+ \}
}
// TODO: Merge this and the next block by introducing a TRIA_AND_DOFHANDLER_TEMPLATES list.
for (deal_II_dimension : DIMENSIONS)
{
+ namespace GridTools \{
#if deal_II_dimension != 1
template
std::map< Triangulation<deal_II_dimension-1,deal_II_dimension>::cell_iterator,
Triangulation<deal_II_dimension>::face_iterator>
- GridTools::extract_boundary_mesh (const Triangulation<deal_II_dimension> &volume_mesh,
+ extract_boundary_mesh (const Triangulation<deal_II_dimension> &volume_mesh,
Triangulation<deal_II_dimension-1,deal_II_dimension> &surface_mesh,
const std::set<unsigned char> &boundary_ids);
#endif
+ \}
}
for (deal_II_dimension : DIMENSIONS; Container : DOFHANDLER_TEMPLATES)
{
+ namespace GridTools \{
#if deal_II_dimension != 1
template
std::map< Container<deal_II_dimension-1,deal_II_dimension>::cell_iterator,
Container<deal_II_dimension>::face_iterator>
- GridTools::extract_boundary_mesh (const Container<deal_II_dimension> &volume_mesh,
+ extract_boundary_mesh (const Container<deal_II_dimension> &volume_mesh,
Container<deal_II_dimension-1,deal_II_dimension> &surface_mesh,
const std::set<unsigned char> &boundary_ids);
#endif
+ \}
}
// $Id$
// Version: $Name$
//
-// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by the deal.II authors
+// Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
DEAL_II_NAMESPACE_OPEN
-
- // specializations for 1D
-template <>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<1,1>&,
- const unsigned int,
- std::vector<unsigned int>&,
- const DoFTools::Coupling)
+namespace MGTools
{
- Assert(false, ExcNotImplemented());
-}
-
-
-template <>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<1,1>&,
- const unsigned int,
- std::vector<unsigned int>&,
- const Table<2,DoFTools::Coupling>&,
- const Table<2,DoFTools::Coupling>&)
-{
- Assert(false, ExcNotImplemented());
-}
-
-
-template <>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<1,2>&,
- const unsigned int,
- std::vector<unsigned int>&,
- const DoFTools::Coupling)
-{
- Assert(false, ExcNotImplemented());
-}
-
-
-template <>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<1,2>&,
- const unsigned int,
- std::vector<unsigned int>&,
- const Table<2,DoFTools::Coupling>&,
- const Table<2,DoFTools::Coupling>&)
-{
- Assert(false, ExcNotImplemented());
-}
+ // specializations for 1D
+ template <>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<1,1>&,
+ const unsigned int,
+ std::vector<unsigned int>&,
+ const DoFTools::Coupling)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+
+ template <>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<1,1>&,
+ const unsigned int,
+ std::vector<unsigned int>&,
+ const Table<2,DoFTools::Coupling>&,
+ const Table<2,DoFTools::Coupling>&)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+
+ template <>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<1,2>&,
+ const unsigned int,
+ std::vector<unsigned int>&,
+ const DoFTools::Coupling)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+ template <>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<1,2>&,
+ const unsigned int,
+ std::vector<unsigned int>&,
+ const Table<2,DoFTools::Coupling>&,
+ const Table<2,DoFTools::Coupling>&)
+ {
+ Assert(false, ExcNotImplemented());
+ }
// Template for 2D and 3D. For 1D see specialization above
-template <int dim, int spacedim>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<dim,spacedim>& dofs,
- const unsigned int level,
- std::vector<unsigned int>& row_lengths,
- const DoFTools::Coupling flux_coupling)
-{
- Assert (row_lengths.size() == dofs.n_dofs(),
- ExcDimensionMismatch(row_lengths.size(), dofs.n_dofs()));
-
- // Function starts here by
- // resetting the counters.
- std::fill(row_lengths.begin(), row_lengths.end(), 0);
- // We need the user flags, so we
- // save them for later restoration
- std::vector<bool> old_flags;
- // We need a non-constant
- // triangulation for the user
- // flags. Since we restore them in
- // the end, this cast is safe.
- Triangulation<dim,spacedim>& user_flags_triangulation =
- const_cast<Triangulation<dim,spacedim>&> (dofs.get_tria());
- user_flags_triangulation.save_user_flags(old_flags);
- user_flags_triangulation.clear_user_flags();
-
- const typename MGDoFHandler<dim,spacedim>::cell_iterator end = dofs.end(level);
- typename MGDoFHandler<dim,spacedim>::active_cell_iterator cell;
- std::vector<unsigned int> cell_indices;
- std::vector<unsigned int> neighbor_indices;
-
- // We loop over cells and go from
- // cells to lower dimensional
- // objects. This is the only way to
- // cope with the fact, that an
- // unknown number of cells may
- // share an object of dimension
- // smaller than dim-1.
- for (cell = dofs.begin(level); cell != end; ++cell)
- {
- const FiniteElement<dim>& fe = cell->get_fe();
- cell_indices.resize(fe.dofs_per_cell);
- cell->get_mg_dof_indices(cell_indices);
- unsigned int i = 0;
- // First, dofs on
- // vertices. We assume that
- // each vertex dof couples
- // with all dofs on
- // adjacent grid cells.
-
- // Adding all dofs of the cells
- // will add dofs of the faces
- // of the cell adjacent to the
- // vertex twice. Therefore, we
- // subtract these here and add
- // them in a loop over the
- // faces below.
-
- // in 1d, faces and vertices
- // are identical. Nevertheless,
- // this will only work if
- // dofs_per_face is zero and
- // dofs_per_vertex is
- // arbitrary, not the other way
- // round.
+ template <int dim, int spacedim>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<dim,spacedim>& dofs,
+ const unsigned int level,
+ std::vector<unsigned int>& row_lengths,
+ const DoFTools::Coupling flux_coupling)
+ {
+ Assert (row_lengths.size() == dofs.n_dofs(),
+ ExcDimensionMismatch(row_lengths.size(), dofs.n_dofs()));
+
+ // Function starts here by
+ // resetting the counters.
+ std::fill(row_lengths.begin(), row_lengths.end(), 0);
+ // We need the user flags, so we
+ // save them for later restoration
+ std::vector<bool> old_flags;
+ // We need a non-constant
+ // triangulation for the user
+ // flags. Since we restore them in
+ // the end, this cast is safe.
+ Triangulation<dim,spacedim>& user_flags_triangulation =
+ const_cast<Triangulation<dim,spacedim>&> (dofs.get_tria());
+ user_flags_triangulation.save_user_flags(old_flags);
+ user_flags_triangulation.clear_user_flags();
+
+ const typename MGDoFHandler<dim,spacedim>::cell_iterator end = dofs.end(level);
+ typename MGDoFHandler<dim,spacedim>::active_cell_iterator cell;
+ std::vector<unsigned int> cell_indices;
+ std::vector<unsigned int> neighbor_indices;
+
+ // We loop over cells and go from
+ // cells to lower dimensional
+ // objects. This is the only way to
+ // cope with the fact, that an
+ // unknown number of cells may
+ // share an object of dimension
+ // smaller than dim-1.
+ for (cell = dofs.begin(level); cell != end; ++cell)
+ {
+ const FiniteElement<dim>& fe = cell->get_fe();
+ cell_indices.resize(fe.dofs_per_cell);
+ cell->get_mg_dof_indices(cell_indices);
+ unsigned int i = 0;
+ // First, dofs on
+ // vertices. We assume that
+ // each vertex dof couples
+ // with all dofs on
+ // adjacent grid cells.
+
+ // Adding all dofs of the cells
+ // will add dofs of the faces
+ // of the cell adjacent to the
+ // vertex twice. Therefore, we
+ // subtract these here and add
+ // them in a loop over the
+ // faces below.
+
+ // in 1d, faces and vertices
+ // are identical. Nevertheless,
+ // this will only work if
+ // dofs_per_face is zero and
+ // dofs_per_vertex is
+ // arbitrary, not the other way
+ // round.
//TODO: This assumes that even in hp context, the dofs per face coincide!
- unsigned int increment = fe.dofs_per_cell - dim * fe.dofs_per_face;
- while (i < fe.first_line_index)
- row_lengths[cell_indices[i++]] += increment;
- // From now on, if an object is
- // a cell, its dofs only couple
- // inside the cell. Since the
- // faces are handled below, we
- // have to subtract ALL faces
- // in this case.
-
- // In all other cases we
- // subtract adjacent faces to be
- // added in the loop below.
- increment = (dim>1)
- ? fe.dofs_per_cell - (dim-1) * fe.dofs_per_face
- : fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
- while (i < fe.first_quad_index)
- row_lengths[cell_indices[i++]] += increment;
-
- // Now quads in 2D and 3D
- increment = (dim>2)
- ? fe.dofs_per_cell - (dim-2) * fe.dofs_per_face
- : fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
- while (i < fe.first_hex_index)
- row_lengths[cell_indices[i++]] += increment;
- // Finally, cells in 3D
- increment = fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
- while (i < fe.dofs_per_cell)
- row_lengths[cell_indices[i++]] += increment;
-
- // At this point, we have
- // counted all dofs
- // contributiong from cells
- // coupled topologically to the
- // adjacent cells, but we
- // subtracted some faces.
-
- // Now, let's go by the faces
- // and add the missing
- // contribution as well as the
- // flux contributions.
- for (unsigned int iface=0;iface<GeometryInfo<dim>::faces_per_cell;++iface)
- {
- bool level_boundary = cell->at_boundary(iface);
- typename MGDoFHandler<dim,spacedim>::cell_iterator neighbor;
- if (!level_boundary)
- {
- neighbor = cell->neighbor(iface);
- if (static_cast<unsigned int>(neighbor->level()) != level)
- level_boundary = true;
- }
-
- if (level_boundary)
- {
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
- continue;
- }
-
- const FiniteElement<dim>& nfe = neighbor->get_fe();
- typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(iface);
-
- // Flux couplings are
- // computed from both sides
- // for simplicity.
+ unsigned int increment = fe.dofs_per_cell - dim * fe.dofs_per_face;
+ while (i < fe.first_line_index)
+ row_lengths[cell_indices[i++]] += increment;
+ // From now on, if an object is
+ // a cell, its dofs only couple
+ // inside the cell. Since the
+ // faces are handled below, we
+ // have to subtract ALL faces
+ // in this case.
+
+ // In all other cases we
+ // subtract adjacent faces to be
+ // added in the loop below.
+ increment = (dim>1)
+ ? fe.dofs_per_cell - (dim-1) * fe.dofs_per_face
+ : fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
+ while (i < fe.first_quad_index)
+ row_lengths[cell_indices[i++]] += increment;
+
+ // Now quads in 2D and 3D
+ increment = (dim>2)
+ ? fe.dofs_per_cell - (dim-2) * fe.dofs_per_face
+ : fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
+ while (i < fe.first_hex_index)
+ row_lengths[cell_indices[i++]] += increment;
+ // Finally, cells in 3D
+ increment = fe.dofs_per_cell - GeometryInfo<dim>::faces_per_cell * fe.dofs_per_face;
+ while (i < fe.dofs_per_cell)
+ row_lengths[cell_indices[i++]] += increment;
+
+ // At this point, we have
+ // counted all dofs
+ // contributiong from cells
+ // coupled topologically to the
+ // adjacent cells, but we
+ // subtracted some faces.
+
+ // Now, let's go by the faces
+ // and add the missing
+ // contribution as well as the
+ // flux contributions.
+ for (unsigned int iface=0;iface<GeometryInfo<dim>::faces_per_cell;++iface)
+ {
+ bool level_boundary = cell->at_boundary(iface);
+ typename MGDoFHandler<dim,spacedim>::cell_iterator neighbor;
+ if (!level_boundary)
+ {
+ neighbor = cell->neighbor(iface);
+ if (static_cast<unsigned int>(neighbor->level()) != level)
+ level_boundary = true;
+ }
- // The dofs on the common face
- // will be handled below,
- // therefore, we subtract them
- // here.
- if (flux_coupling != DoFTools::none)
- {
- unsigned int increment = nfe.dofs_per_cell - nfe.dofs_per_face;
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- row_lengths[cell_indices[i]] += increment;
- }
+ if (level_boundary)
+ {
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
+ row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ continue;
+ }
- // Do this only once per
- // face.
- if (face->user_flag_set())
- continue;
- face->set_user_flag();
- // At this point, we assume
- // that each cell added its
- // dofs minus the face to
- // the couplings of the
- // face dofs. Since we
- // subtracted two faces, we
- // have to re-add one.
-
- // If one side of the face
- // is refined, all the fine
- // face dofs couple with
- // the coarse one.
- neighbor_indices.resize(nfe.dofs_per_cell);
- neighbor->get_mg_dof_indices(neighbor_indices);
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- row_lengths[cell_indices[i]] += nfe.dofs_per_face;
- for (unsigned int i=0;i<nfe.dofs_per_cell;++i)
- row_lengths[neighbor_indices[i]] += fe.dofs_per_face;
- }
- }
- user_flags_triangulation.load_user_flags(old_flags);
-}
+ const FiniteElement<dim>& nfe = neighbor->get_fe();
+ typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(iface);
+ // Flux couplings are
+ // computed from both sides
+ // for simplicity.
-// This is the template for 2D and 3D. See version for 1D above
-template <int dim, int spacedim>
-void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<dim,spacedim>& dofs,
- const unsigned int level,
- std::vector<unsigned int>& row_lengths,
- const Table<2,DoFTools::Coupling>& couplings,
- const Table<2,DoFTools::Coupling>& flux_couplings)
-{
- Assert (row_lengths.size() == dofs.n_dofs(),
- ExcDimensionMismatch(row_lengths.size(), dofs.n_dofs()));
-
- // Function starts here by
- // resetting the counters.
- std::fill(row_lengths.begin(), row_lengths.end(), 0);
- // We need the user flags, so we
- // save them for later restoration
- std::vector<bool> old_flags;
- // We need a non-constant
- // triangulation for the user
- // flags. Since we restore them in
- // the end, this cast is safe.
- Triangulation<dim,spacedim>& user_flags_triangulation =
- const_cast<Triangulation<dim,spacedim>&> (dofs.get_tria());
- user_flags_triangulation.save_user_flags(old_flags);
- user_flags_triangulation.clear_user_flags();
-
- const typename MGDoFHandler<dim,spacedim>::cell_iterator end = dofs.end(level);
- typename MGDoFHandler<dim,spacedim>::active_cell_iterator cell;
- std::vector<unsigned int> cell_indices;
- std::vector<unsigned int> neighbor_indices;
-
- // We have to translate the
- // couplings from components to
- // blocks, so this works for
- // nonprimitive elements as well.
- std::vector<Table<2, DoFTools::Coupling> > couple_cell;
- std::vector<Table<2, DoFTools::Coupling> > couple_face;
- DoFTools::convert_couplings_to_blocks(dofs, couplings, couple_cell);
- DoFTools::convert_couplings_to_blocks(dofs, flux_couplings, couple_face);
-
- // We loop over cells and go from
- // cells to lower dimensional
- // objects. This is the only way to
- // cope withthe fact, that an
- // unknown number of cells may
- // share an object of dimension
- // smaller than dim-1.
- for (cell = dofs.begin_active(); cell != end; ++cell)
- {
- const FiniteElement<dim>& fe = cell->get_fe();
- const unsigned int fe_index = cell->active_fe_index();
-
- Assert (couplings.n_rows()==fe.n_components(),
- ExcDimensionMismatch(couplings.n_rows(), fe.n_components()));
- Assert (couplings.n_cols()==fe.n_components(),
- ExcDimensionMismatch(couplings.n_cols(), fe.n_components()));
- Assert (flux_couplings.n_rows()==fe.n_components(),
- ExcDimensionMismatch(flux_couplings.n_rows(), fe.n_components()));
- Assert (flux_couplings.n_cols()==fe.n_components(),
- ExcDimensionMismatch(flux_couplings.n_cols(), fe.n_components()));
-
- cell_indices.resize(fe.dofs_per_cell);
- cell->get_mg_dof_indices(cell_indices);
- unsigned int i = 0;
- // First, dofs on
- // vertices. We assume that
- // each vertex dof couples
- // with all dofs on
- // adjacent grid cells.
-
- // Adding all dofs of the cells
- // will add dofs of the faces
- // of the cell adjacent to the
- // vertex twice. Therefore, we
- // subtract these here and add
- // them in a loop over the
- // faces below.
-
- // in 1d, faces and vertices
- // are identical. Nevertheless,
- // this will only work if
- // dofs_per_face is zero and
- // dofs_per_vertex is
- // arbitrary, not the other way
- // round.
- unsigned int increment;
- while (i < fe.first_line_index)
- {
- for (unsigned int base=0;base<fe.n_base_elements();++base)
- for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
- if (couple_cell[fe_index](fe.system_to_block_index(i).first,
- fe.first_block_of_base(base) + mult) != DoFTools::none)
- {
- increment = fe.base_element(base).dofs_per_cell
- - dim * fe.base_element(base).dofs_per_face;
+ // The dofs on the common face
+ // will be handled below,
+ // therefore, we subtract them
+ // here.
+ if (flux_coupling != DoFTools::none)
+ {
+ unsigned int increment = nfe.dofs_per_cell - nfe.dofs_per_face;
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
row_lengths[cell_indices[i]] += increment;
- }
- ++i;
- }
- // From now on, if an object is
- // a cell, its dofs only couple
- // inside the cell. Since the
- // faces are handled below, we
- // have to subtract ALL faces
- // in this case.
-
- // In all other cases we
- // subtract adjacent faces to be
- // added in the loop below.
- while (i < fe.first_quad_index)
- {
- for (unsigned int base=0;base<fe.n_base_elements();++base)
- for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
- if (couple_cell[fe_index](fe.system_to_block_index(i).first,
- fe.first_block_of_base(base) + mult) != DoFTools::none)
- {
- increment = fe.base_element(base).dofs_per_cell
- - ((dim>1)
- ? (dim-1)
- : GeometryInfo<dim>::faces_per_cell)
- * fe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
- }
- ++i;
- }
-
- // Now quads in 2D and 3D
- while (i < fe.first_hex_index)
- {
- for (unsigned int base=0;base<fe.n_base_elements();++base)
- for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
- if (couple_cell[fe_index](fe.system_to_block_index(i).first,
- fe.first_block_of_base(base) + mult) != DoFTools::none)
- {
- increment = fe.base_element(base).dofs_per_cell
- - ((dim>2)
- ? (dim-2)
- : GeometryInfo<dim>::faces_per_cell)
- * fe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
}
- ++i;
- }
- // Finally, cells in 3D
- while (i < fe.dofs_per_cell)
- {
- for (unsigned int base=0;base<fe.n_base_elements();++base)
- for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
- if (couple_cell[fe_index](fe.system_to_block_index(i).first,
- fe.first_block_of_base(base) + mult) != DoFTools::none)
- {
- increment = fe.base_element(base).dofs_per_cell
- - GeometryInfo<dim>::faces_per_cell
- * fe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
- }
- ++i;
- }
-
- // At this point, we have
- // counted all dofs
- // contributiong from cells
- // coupled topologically to the
- // adjacent cells, but we
- // subtracted some faces.
-
- // Now, let's go by the faces
- // and add the missing
- // contribution as well as the
- // flux contributions.
- for (unsigned int iface=0;iface<GeometryInfo<dim>::faces_per_cell;++iface)
- {
- bool level_boundary = cell->at_boundary(iface);
- typename MGDoFHandler<dim,spacedim>::cell_iterator neighbor;
- if (!level_boundary)
- {
- neighbor = cell->neighbor(iface);
- if (static_cast<unsigned int>(neighbor->level()) != level)
- level_boundary = true;
- }
-
- if (level_boundary)
- {
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ // Do this only once per
+ // face.
+ if (face->user_flag_set())
continue;
- }
+ face->set_user_flag();
+ // At this point, we assume
+ // that each cell added its
+ // dofs minus the face to
+ // the couplings of the
+ // face dofs. Since we
+ // subtracted two faces, we
+ // have to re-add one.
+
+ // If one side of the face
+ // is refined, all the fine
+ // face dofs couple with
+ // the coarse one.
+ neighbor_indices.resize(nfe.dofs_per_cell);
+ neighbor->get_mg_dof_indices(neighbor_indices);
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
+ row_lengths[cell_indices[i]] += nfe.dofs_per_face;
+ for (unsigned int i=0;i<nfe.dofs_per_cell;++i)
+ row_lengths[neighbor_indices[i]] += fe.dofs_per_face;
+ }
+ }
+ user_flags_triangulation.load_user_flags(old_flags);
+ }
- const FiniteElement<dim>& nfe = neighbor->get_fe();
- typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(iface);
-
- // Flux couplings are
- // computed from both sides
- // for simplicity.
-
- // The dofs on the common face
- // will be handled below,
- // therefore, we subtract them
- // here.
- for (unsigned int base=0;base<nfe.n_base_elements();++base)
- for (unsigned int mult=0;mult<nfe.element_multiplicity(base);++mult)
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- if (couple_face[fe_index](fe.system_to_block_index(i).first,
- nfe.first_block_of_base(base) + mult) != DoFTools::none)
- {
- unsigned int increment = nfe.base_element(base).dofs_per_cell
- - nfe.base_element(base).dofs_per_face;
- row_lengths[cell_indices[i]] += increment;
- }
- // Do this only once per
- // face and not on the
- // hanging faces.
- if (face->user_flag_set())
- continue;
- face->set_user_flag();
- // At this point, we assume
- // that each cell added its
- // dofs minus the face to
- // the couplings of the
- // face dofs. Since we
- // subtracted two faces, we
- // have to re-add one.
-
- // If one side of the face
- // is refined, all the fine
- // face dofs couple with
- // the coarse one.
-
- // Wolfgang, do they couple
- // with each other by
- // constraints?
-
- // This will not work with
- // different couplings on
- // different cells.
- neighbor_indices.resize(nfe.dofs_per_cell);
- neighbor->get_mg_dof_indices(neighbor_indices);
- for (unsigned int base=0;base<nfe.n_base_elements();++base)
- for (unsigned int mult=0;mult<nfe.element_multiplicity(base);++mult)
- for (unsigned int i=0;i<fe.dofs_per_cell;++i)
- if (couple_cell[fe_index](fe.system_to_component_index(i).first,
- nfe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[cell_indices[i]]
- += nfe.base_element(base).dofs_per_face;
- for (unsigned int base=0;base<fe.n_base_elements();++base)
- for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
- for (unsigned int i=0;i<nfe.dofs_per_cell;++i)
- if (couple_cell[fe_index](nfe.system_to_component_index(i).first,
+// This is the template for 2D and 3D. See version for 1D above
+ template <int dim, int spacedim>
+ void
+ compute_row_length_vector(
+ const MGDoFHandler<dim,spacedim>& dofs,
+ const unsigned int level,
+ std::vector<unsigned int>& row_lengths,
+ const Table<2,DoFTools::Coupling>& couplings,
+ const Table<2,DoFTools::Coupling>& flux_couplings)
+ {
+ Assert (row_lengths.size() == dofs.n_dofs(),
+ ExcDimensionMismatch(row_lengths.size(), dofs.n_dofs()));
+
+ // Function starts here by
+ // resetting the counters.
+ std::fill(row_lengths.begin(), row_lengths.end(), 0);
+ // We need the user flags, so we
+ // save them for later restoration
+ std::vector<bool> old_flags;
+ // We need a non-constant
+ // triangulation for the user
+ // flags. Since we restore them in
+ // the end, this cast is safe.
+ Triangulation<dim,spacedim>& user_flags_triangulation =
+ const_cast<Triangulation<dim,spacedim>&> (dofs.get_tria());
+ user_flags_triangulation.save_user_flags(old_flags);
+ user_flags_triangulation.clear_user_flags();
+
+ const typename MGDoFHandler<dim,spacedim>::cell_iterator end = dofs.end(level);
+ typename MGDoFHandler<dim,spacedim>::active_cell_iterator cell;
+ std::vector<unsigned int> cell_indices;
+ std::vector<unsigned int> neighbor_indices;
+
+ // We have to translate the
+ // couplings from components to
+ // blocks, so this works for
+ // nonprimitive elements as well.
+ std::vector<Table<2, DoFTools::Coupling> > couple_cell;
+ std::vector<Table<2, DoFTools::Coupling> > couple_face;
+ DoFTools::convert_couplings_to_blocks(dofs, couplings, couple_cell);
+ DoFTools::convert_couplings_to_blocks(dofs, flux_couplings, couple_face);
+
+ // We loop over cells and go from
+ // cells to lower dimensional
+ // objects. This is the only way to
+ // cope withthe fact, that an
+ // unknown number of cells may
+ // share an object of dimension
+ // smaller than dim-1.
+ for (cell = dofs.begin_active(); cell != end; ++cell)
+ {
+ const FiniteElement<dim>& fe = cell->get_fe();
+ const unsigned int fe_index = cell->active_fe_index();
+
+ Assert (couplings.n_rows()==fe.n_components(),
+ ExcDimensionMismatch(couplings.n_rows(), fe.n_components()));
+ Assert (couplings.n_cols()==fe.n_components(),
+ ExcDimensionMismatch(couplings.n_cols(), fe.n_components()));
+ Assert (flux_couplings.n_rows()==fe.n_components(),
+ ExcDimensionMismatch(flux_couplings.n_rows(), fe.n_components()));
+ Assert (flux_couplings.n_cols()==fe.n_components(),
+ ExcDimensionMismatch(flux_couplings.n_cols(), fe.n_components()));
+
+ cell_indices.resize(fe.dofs_per_cell);
+ cell->get_mg_dof_indices(cell_indices);
+ unsigned int i = 0;
+ // First, dofs on
+ // vertices. We assume that
+ // each vertex dof couples
+ // with all dofs on
+ // adjacent grid cells.
+
+ // Adding all dofs of the cells
+ // will add dofs of the faces
+ // of the cell adjacent to the
+ // vertex twice. Therefore, we
+ // subtract these here and add
+ // them in a loop over the
+ // faces below.
+
+ // in 1d, faces and vertices
+ // are identical. Nevertheless,
+ // this will only work if
+ // dofs_per_face is zero and
+ // dofs_per_vertex is
+ // arbitrary, not the other way
+ // round.
+ unsigned int increment;
+ while (i < fe.first_line_index)
+ {
+ for (unsigned int base=0;base<fe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
+ if (couple_cell[fe_index](fe.system_to_block_index(i).first,
fe.first_block_of_base(base) + mult) != DoFTools::none)
- row_lengths[neighbor_indices[i]]
- += fe.base_element(base).dofs_per_face;
- }
- }
- user_flags_triangulation.load_user_flags(old_flags);
-}
-
+ {
+ increment = fe.base_element(base).dofs_per_cell
+ - dim * fe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[i]] += increment;
+ }
+ ++i;
+ }
+ // From now on, if an object is
+ // a cell, its dofs only couple
+ // inside the cell. Since the
+ // faces are handled below, we
+ // have to subtract ALL faces
+ // in this case.
+
+ // In all other cases we
+ // subtract adjacent faces to be
+ // added in the loop below.
+ while (i < fe.first_quad_index)
+ {
+ for (unsigned int base=0;base<fe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
+ if (couple_cell[fe_index](fe.system_to_block_index(i).first,
+ fe.first_block_of_base(base) + mult) != DoFTools::none)
+ {
+ increment = fe.base_element(base).dofs_per_cell
+ - ((dim>1)
+ ? (dim-1)
+ : GeometryInfo<dim>::faces_per_cell)
+ * fe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[i]] += increment;
+ }
+ ++i;
+ }
+ // Now quads in 2D and 3D
+ while (i < fe.first_hex_index)
+ {
+ for (unsigned int base=0;base<fe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
+ if (couple_cell[fe_index](fe.system_to_block_index(i).first,
+ fe.first_block_of_base(base) + mult) != DoFTools::none)
+ {
+ increment = fe.base_element(base).dofs_per_cell
+ - ((dim>2)
+ ? (dim-2)
+ : GeometryInfo<dim>::faces_per_cell)
+ * fe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[i]] += increment;
+ }
+ ++i;
+ }
-template <int dim, class SparsityPattern, int spacedim>
-void MGTools::make_sparsity_pattern (
- const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level)
-{
- const unsigned int n_dofs = dof.n_dofs(level);
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-
- const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
- std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
- typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
- endc = dof.end(level);
- for (; cell!=endc; ++cell)
- {
- cell->get_mg_dof_indices (dofs_on_this_cell);
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- }
-}
+ // Finally, cells in 3D
+ while (i < fe.dofs_per_cell)
+ {
+ for (unsigned int base=0;base<fe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
+ if (couple_cell[fe_index](fe.system_to_block_index(i).first,
+ fe.first_block_of_base(base) + mult) != DoFTools::none)
+ {
+ increment = fe.base_element(base).dofs_per_cell
+ - GeometryInfo<dim>::faces_per_cell
+ * fe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[i]] += increment;
+ }
+ ++i;
+ }
+ // At this point, we have
+ // counted all dofs
+ // contributiong from cells
+ // coupled topologically to the
+ // adjacent cells, but we
+ // subtracted some faces.
+
+ // Now, let's go by the faces
+ // and add the missing
+ // contribution as well as the
+ // flux contributions.
+ for (unsigned int iface=0;iface<GeometryInfo<dim>::faces_per_cell;++iface)
+ {
+ bool level_boundary = cell->at_boundary(iface);
+ typename MGDoFHandler<dim,spacedim>::cell_iterator neighbor;
+ if (!level_boundary)
+ {
+ neighbor = cell->neighbor(iface);
+ if (static_cast<unsigned int>(neighbor->level()) != level)
+ level_boundary = true;
+ }
+ if (level_boundary)
+ {
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
+ row_lengths[cell_indices[i]] += fe.dofs_per_face;
+ continue;
+ }
-template <int dim, class SparsityPattern, int spacedim>
-void
-MGTools::make_flux_sparsity_pattern (
- const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level)
-{
- const unsigned int n_dofs = dof.n_dofs(level);
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-
- const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
- std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
- std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
- typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
- endc = dof.end(level);
- for (; cell!=endc; ++cell)
- {
- cell->get_mg_dof_indices (dofs_on_this_cell);
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
-
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- if ( (! cell->at_boundary(face)) &&
- (static_cast<unsigned int>(cell->neighbor_level(face)) == level) )
- {
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(face);
- neighbor->get_mg_dof_indices (dofs_on_other_cell);
- // only add one direction
- // The other is taken care of
- // by neighbor.
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
+ const FiniteElement<dim>& nfe = neighbor->get_fe();
+ typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(iface);
+
+ // Flux couplings are
+ // computed from both sides
+ // for simplicity.
+
+ // The dofs on the common face
+ // will be handled below,
+ // therefore, we subtract them
+ // here.
+ for (unsigned int base=0;base<nfe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<nfe.element_multiplicity(base);++mult)
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
+ if (couple_face[fe_index](fe.system_to_block_index(i).first,
+ nfe.first_block_of_base(base) + mult) != DoFTools::none)
{
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
+ unsigned int increment = nfe.base_element(base).dofs_per_cell
+ - nfe.base_element(base).dofs_per_face;
+ row_lengths[cell_indices[i]] += increment;
}
- }
- }
- }
- }
-}
-
+ // Do this only once per
+ // face and not on the
+ // hanging faces.
+ if (face->user_flag_set())
+ continue;
+ face->set_user_flag();
+ // At this point, we assume
+ // that each cell added its
+ // dofs minus the face to
+ // the couplings of the
+ // face dofs. Since we
+ // subtracted two faces, we
+ // have to re-add one.
+
+ // If one side of the face
+ // is refined, all the fine
+ // face dofs couple with
+ // the coarse one.
+
+ // Wolfgang, do they couple
+ // with each other by
+ // constraints?
+
+ // This will not work with
+ // different couplings on
+ // different cells.
+ neighbor_indices.resize(nfe.dofs_per_cell);
+ neighbor->get_mg_dof_indices(neighbor_indices);
+ for (unsigned int base=0;base<nfe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<nfe.element_multiplicity(base);++mult)
+ for (unsigned int i=0;i<fe.dofs_per_cell;++i)
+ if (couple_cell[fe_index](fe.system_to_component_index(i).first,
+ nfe.first_block_of_base(base) + mult) != DoFTools::none)
+ row_lengths[cell_indices[i]]
+ += nfe.base_element(base).dofs_per_face;
+ for (unsigned int base=0;base<fe.n_base_elements();++base)
+ for (unsigned int mult=0;mult<fe.element_multiplicity(base);++mult)
+ for (unsigned int i=0;i<nfe.dofs_per_cell;++i)
+ if (couple_cell[fe_index](nfe.system_to_component_index(i).first,
+ fe.first_block_of_base(base) + mult) != DoFTools::none)
+ row_lengths[neighbor_indices[i]]
+ += fe.base_element(base).dofs_per_face;
+ }
+ }
+ user_flags_triangulation.load_user_flags(old_flags);
+ }
-template <int dim, class SparsityPattern, int spacedim>
-void
-MGTools::make_flux_sparsity_pattern_edge (
- const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level)
-{
- Assert ((level>=1) && (level<dof.get_tria().n_levels()),
- ExcIndexRange(level, 1, dof.get_tria().n_levels()));
-
- const unsigned int fine_dofs = dof.n_dofs(level);
- const unsigned int coarse_dofs = dof.n_dofs(level-1);
-
- // Matrix maps from fine level to coarse level
-
- Assert (sparsity.n_rows() == coarse_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), coarse_dofs));
- Assert (sparsity.n_cols() == fine_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), fine_dofs));
-
- const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
- std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
- std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
- typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
- endc = dof.end(level);
- for (; cell!=endc; ++cell)
- {
- cell->get_mg_dof_indices (dofs_on_this_cell);
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- // Neighbor is coarser
-
- if ( (! cell->at_boundary(face)) &&
- (static_cast<unsigned int>(cell->neighbor_level(face)) != level) )
- {
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(face);
- neighbor->get_mg_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- {
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- }
- }
- }
- }
- }
-}
+ template <int dim, class SparsityPattern, int spacedim>
+ void make_sparsity_pattern (
+ const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level)
+ {
+ const unsigned int n_dofs = dof.n_dofs(level);
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
-template <int dim, class SparsityPattern, int spacedim>
-void
-MGTools::make_flux_sparsity_pattern (
- const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level,
- const Table<2,DoFTools::Coupling> &int_mask,
- const Table<2,DoFTools::Coupling> &flux_mask)
-{
- const FiniteElement<dim>& fe = dof.get_fe();
- const unsigned int n_dofs = dof.n_dofs(level);
- const unsigned int n_comp = fe.n_components();
-
- Assert (sparsity.n_rows() == n_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
- Assert (sparsity.n_cols() == n_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
- Assert (int_mask.n_rows() == n_comp,
- ExcDimensionMismatch (int_mask.n_rows(), n_comp));
- Assert (int_mask.n_cols() == n_comp,
- ExcDimensionMismatch (int_mask.n_cols(), n_comp));
- Assert (flux_mask.n_rows() == n_comp,
- ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
- Assert (flux_mask.n_cols() == n_comp,
- ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
-
- const unsigned int total_dofs = fe.dofs_per_cell;
- std::vector<unsigned int> dofs_on_this_cell(total_dofs);
- std::vector<unsigned int> dofs_on_other_cell(total_dofs);
- Table<2,bool> support_on_face(total_dofs, GeometryInfo<dim>::faces_per_cell);
-
- typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
- endc = dof.end(level);
-
- const Table<2,DoFTools::Coupling>
- int_dof_mask = DoFTools::dof_couplings_from_component_couplings(fe, int_mask),
- flux_dof_mask = DoFTools::dof_couplings_from_component_couplings(fe, flux_mask);
-
- for (unsigned int i=0; i<total_dofs; ++i)
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell;++f)
- support_on_face(i,f) = fe.has_support_on_face(i,f);
-
- // Clear user flags because we will
- // need them. But first we save
- // them and make sure that we
- // restore them later such that at
- // the end of this function the
- // Triangulation will be in the
- // same state as it was at the
- // beginning of this function.
- std::vector<bool> user_flags;
- dof.get_tria().save_user_flags(user_flags);
- const_cast<Triangulation<dim,spacedim> &>(dof.get_tria()).clear_user_flags ();
-
- for (; cell!=endc; ++cell)
- {
- cell->get_mg_dof_indices (dofs_on_this_cell);
- // make sparsity pattern for this cell
- for (unsigned int i=0; i<total_dofs; ++i)
- for (unsigned int j=0; j<total_dofs; ++j)
- if (int_dof_mask[i][j] != DoFTools::none)
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
+ typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
+ endc = dof.end(level);
+ for (; cell!=endc; ++cell)
+ {
+ cell->get_mg_dof_indices (dofs_on_this_cell);
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ }
+ }
+
+
+
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern (
+ const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level)
+ {
+ const unsigned int n_dofs = dof.n_dofs(level);
+
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
+ std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
+ typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
+ endc = dof.end(level);
+ for (; cell!=endc; ++cell)
+ {
+ cell->get_mg_dof_indices (dofs_on_this_cell);
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
sparsity.add (dofs_on_this_cell[i],
dofs_on_this_cell[j]);
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- typename MGDoFHandler<dim,spacedim>::face_iterator cell_face = cell->face(face);
- if (cell_face->user_flag_set ())
- continue;
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ if ( (! cell->at_boundary(face)) &&
+ (static_cast<unsigned int>(cell->neighbor_level(face)) == level) )
+ {
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(face);
+ neighbor->get_mg_dof_indices (dofs_on_other_cell);
+ // only add one direction
+ // The other is taken care of
+ // by neighbor.
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ }
+ }
+ }
+ }
+ }
+ }
- if (cell->at_boundary (face) )
- {
- for (unsigned int i=0; i<total_dofs; ++i)
- {
- const bool i_non_zero_i = support_on_face (i, face);
- for (unsigned int j=0; j<total_dofs; ++j)
- {
- const bool j_non_zero_i = support_on_face (j, face);
- if (flux_dof_mask(i,j) == DoFTools::always)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- if (flux_dof_mask(i,j) == DoFTools::nonzero
- && i_non_zero_i && j_non_zero_i)
- sparsity.add (dofs_on_this_cell[i],
- dofs_on_this_cell[j]);
- }
- }
- }
- else
- {
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(face);
- if (neighbor->level() < cell->level())
- continue;
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern_edge (
+ const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level)
+ {
+ Assert ((level>=1) && (level<dof.get_tria().n_levels()),
+ ExcIndexRange(level, 1, dof.get_tria().n_levels()));
- unsigned int neighbor_face = cell->neighbor_of_neighbor(face);
+ const unsigned int fine_dofs = dof.n_dofs(level);
+ const unsigned int coarse_dofs = dof.n_dofs(level-1);
- neighbor->get_mg_dof_indices (dofs_on_other_cell);
- for (unsigned int i=0; i<total_dofs; ++i)
- {
- const bool i_non_zero_i = support_on_face (i, face);
- const bool i_non_zero_e = support_on_face (i, neighbor_face);
- for (unsigned int j=0; j<total_dofs; ++j)
- {
- const bool j_non_zero_i = support_on_face (j, face);
- const bool j_non_zero_e = support_on_face (j, neighbor_face);
- if (flux_dof_mask(i,j) == DoFTools::always)
- {
+ // Matrix maps from fine level to coarse level
+
+ Assert (sparsity.n_rows() == coarse_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), coarse_dofs));
+ Assert (sparsity.n_cols() == fine_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), fine_dofs));
+
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
+ std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
+ typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
+ endc = dof.end(level);
+ for (; cell!=endc; ++cell)
+ {
+ cell->get_mg_dof_indices (dofs_on_this_cell);
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ // Neighbor is coarser
+
+ if ( (! cell->at_boundary(face)) &&
+ (static_cast<unsigned int>(cell->neighbor_level(face)) != level) )
+ {
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(face);
+ neighbor->get_mg_dof_indices (dofs_on_other_cell);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern (
+ const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level,
+ const Table<2,DoFTools::Coupling> &int_mask,
+ const Table<2,DoFTools::Coupling> &flux_mask)
+ {
+ const FiniteElement<dim>& fe = dof.get_fe();
+ const unsigned int n_dofs = dof.n_dofs(level);
+ const unsigned int n_comp = fe.n_components();
+
+ Assert (sparsity.n_rows() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), n_dofs));
+ Assert (sparsity.n_cols() == n_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), n_dofs));
+ Assert (int_mask.n_rows() == n_comp,
+ ExcDimensionMismatch (int_mask.n_rows(), n_comp));
+ Assert (int_mask.n_cols() == n_comp,
+ ExcDimensionMismatch (int_mask.n_cols(), n_comp));
+ Assert (flux_mask.n_rows() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
+ Assert (flux_mask.n_cols() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
+
+ const unsigned int total_dofs = fe.dofs_per_cell;
+ std::vector<unsigned int> dofs_on_this_cell(total_dofs);
+ std::vector<unsigned int> dofs_on_other_cell(total_dofs);
+ Table<2,bool> support_on_face(total_dofs, GeometryInfo<dim>::faces_per_cell);
+
+ typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
+ endc = dof.end(level);
+
+ const Table<2,DoFTools::Coupling>
+ int_dof_mask = DoFTools::dof_couplings_from_component_couplings(fe, int_mask),
+ flux_dof_mask = DoFTools::dof_couplings_from_component_couplings(fe, flux_mask);
+
+ for (unsigned int i=0; i<total_dofs; ++i)
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell;++f)
+ support_on_face(i,f) = fe.has_support_on_face(i,f);
+
+ // Clear user flags because we will
+ // need them. But first we save
+ // them and make sure that we
+ // restore them later such that at
+ // the end of this function the
+ // Triangulation will be in the
+ // same state as it was at the
+ // beginning of this function.
+ std::vector<bool> user_flags;
+ dof.get_tria().save_user_flags(user_flags);
+ const_cast<Triangulation<dim,spacedim> &>(dof.get_tria()).clear_user_flags ();
+
+ for (; cell!=endc; ++cell)
+ {
+ cell->get_mg_dof_indices (dofs_on_this_cell);
+ // make sparsity pattern for this cell
+ for (unsigned int i=0; i<total_dofs; ++i)
+ for (unsigned int j=0; j<total_dofs; ++j)
+ if (int_dof_mask[i][j] != DoFTools::none)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ typename MGDoFHandler<dim,spacedim>::face_iterator cell_face = cell->face(face);
+ if (cell_face->user_flag_set ())
+ continue;
+
+ if (cell->at_boundary (face) )
+ {
+ for (unsigned int i=0; i<total_dofs; ++i)
+ {
+ const bool i_non_zero_i = support_on_face (i, face);
+ for (unsigned int j=0; j<total_dofs; ++j)
+ {
+ const bool j_non_zero_i = support_on_face (j, face);
+
+ if (flux_dof_mask(i,j) == DoFTools::always)
sparsity.add (dofs_on_this_cell[i],
- dofs_on_other_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
dofs_on_this_cell[j]);
+ if (flux_dof_mask(i,j) == DoFTools::nonzero
+ && i_non_zero_i && j_non_zero_i)
sparsity.add (dofs_on_this_cell[i],
dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_other_cell[j]);
- }
- if (flux_dof_mask(i,j) == DoFTools::nonzero)
- {
- if (i_non_zero_i && j_non_zero_e)
+ }
+ }
+ }
+ else
+ {
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(face);
+
+ if (neighbor->level() < cell->level())
+ continue;
+
+ unsigned int neighbor_face = cell->neighbor_of_neighbor(face);
+
+ neighbor->get_mg_dof_indices (dofs_on_other_cell);
+ for (unsigned int i=0; i<total_dofs; ++i)
+ {
+ const bool i_non_zero_i = support_on_face (i, face);
+ const bool i_non_zero_e = support_on_face (i, neighbor_face);
+ for (unsigned int j=0; j<total_dofs; ++j)
+ {
+ const bool j_non_zero_i = support_on_face (j, face);
+ const bool j_non_zero_e = support_on_face (j, neighbor_face);
+ if (flux_dof_mask(i,j) == DoFTools::always)
+ {
sparsity.add (dofs_on_this_cell[i],
dofs_on_other_cell[j]);
- if (i_non_zero_e && j_non_zero_i)
sparsity.add (dofs_on_other_cell[i],
dofs_on_this_cell[j]);
- if (i_non_zero_i && j_non_zero_i)
sparsity.add (dofs_on_this_cell[i],
dofs_on_this_cell[j]);
- if (i_non_zero_e && j_non_zero_e)
sparsity.add (dofs_on_other_cell[i],
dofs_on_other_cell[j]);
- }
+ }
+ if (flux_dof_mask(i,j) == DoFTools::nonzero)
+ {
+ if (i_non_zero_i && j_non_zero_e)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_other_cell[j]);
+ if (i_non_zero_e && j_non_zero_i)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_i && j_non_zero_i)
+ sparsity.add (dofs_on_this_cell[i],
+ dofs_on_this_cell[j]);
+ if (i_non_zero_e && j_non_zero_e)
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_other_cell[j]);
+ }
- if (flux_dof_mask(j,i) == DoFTools::always)
- {
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_other_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_this_cell[j],
- dofs_on_this_cell[i]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_other_cell[i]);
- }
- if (flux_dof_mask(j,i) == DoFTools::nonzero)
- {
- if (j_non_zero_i && i_non_zero_e)
+ if (flux_dof_mask(j,i) == DoFTools::always)
+ {
sparsity.add (dofs_on_this_cell[j],
dofs_on_other_cell[i]);
- if (j_non_zero_e && i_non_zero_i)
sparsity.add (dofs_on_other_cell[j],
dofs_on_this_cell[i]);
- if (j_non_zero_i && i_non_zero_i)
sparsity.add (dofs_on_this_cell[j],
dofs_on_this_cell[i]);
- if (j_non_zero_e && i_non_zero_e)
sparsity.add (dofs_on_other_cell[j],
dofs_on_other_cell[i]);
- }
- }
- }
- neighbor->face(neighbor_face)->set_user_flag ();
- }
- }
- }
+ }
+ if (flux_dof_mask(j,i) == DoFTools::nonzero)
+ {
+ if (j_non_zero_i && i_non_zero_e)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_other_cell[i]);
+ if (j_non_zero_e && i_non_zero_i)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_i && i_non_zero_i)
+ sparsity.add (dofs_on_this_cell[j],
+ dofs_on_this_cell[i]);
+ if (j_non_zero_e && i_non_zero_e)
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_other_cell[i]);
+ }
+ }
+ }
+ neighbor->face(neighbor_face)->set_user_flag ();
+ }
+ }
+ }
- // finally restore the user flags
- const_cast<Triangulation<dim,spacedim> &>(dof.get_tria()).load_user_flags(user_flags);
-}
+ // finally restore the user flags
+ const_cast<Triangulation<dim,spacedim> &>(dof.get_tria()).load_user_flags(user_flags);
+ }
-template <int dim, class SparsityPattern, int spacedim>
-void
-MGTools::make_flux_sparsity_pattern_edge (
- const MGDoFHandler<dim,spacedim> &dof,
- SparsityPattern &sparsity,
- const unsigned int level,
- const Table<2,DoFTools::Coupling> &flux_mask)
-{
- const FiniteElement<dim>& fe = dof.get_fe();
- const unsigned int n_comp = fe.n_components();
-
- Assert ((level>=1) && (level<dof.get_tria().n_levels()),
- ExcIndexRange(level, 1, dof.get_tria().n_levels()));
-
- const unsigned int fine_dofs = dof.n_dofs(level);
- const unsigned int coarse_dofs = dof.n_dofs(level-1);
-
- // Matrix maps from fine level to coarse level
-
- Assert (sparsity.n_rows() == coarse_dofs,
- ExcDimensionMismatch (sparsity.n_rows(), coarse_dofs));
- Assert (sparsity.n_cols() == fine_dofs,
- ExcDimensionMismatch (sparsity.n_cols(), fine_dofs));
- Assert (flux_mask.n_rows() == n_comp,
- ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
- Assert (flux_mask.n_cols() == n_comp,
- ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
-
- const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
- std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
- std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
- Table<2,bool> support_on_face(dofs_per_cell, GeometryInfo<dim>::faces_per_cell);
-
- typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
- endc = dof.end(level);
-
- const Table<2,DoFTools::Coupling> flux_dof_mask
- = DoFTools::dof_couplings_from_component_couplings(fe, flux_mask);
-
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell;++f)
- support_on_face(i,f) = fe.has_support_on_face(i,f);
-
- for (; cell!=endc; ++cell)
- {
- cell->get_mg_dof_indices (dofs_on_this_cell);
- // Loop over all interior neighbors
- for (unsigned int face = 0;
- face < GeometryInfo<dim>::faces_per_cell;
- ++face)
- {
- // Neighbor is coarser
+ template <int dim, class SparsityPattern, int spacedim>
+ void
+ make_flux_sparsity_pattern_edge (
+ const MGDoFHandler<dim,spacedim> &dof,
+ SparsityPattern &sparsity,
+ const unsigned int level,
+ const Table<2,DoFTools::Coupling> &flux_mask)
+ {
+ const FiniteElement<dim>& fe = dof.get_fe();
+ const unsigned int n_comp = fe.n_components();
- if ( (! cell->at_boundary(face)) &&
- (static_cast<unsigned int>(cell->neighbor_level(face)) != level) )
- {
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- neighbor = cell->neighbor(face);
- neighbor->get_mg_dof_indices (dofs_on_other_cell);
+ Assert ((level>=1) && (level<dof.get_tria().n_levels()),
+ ExcIndexRange(level, 1, dof.get_tria().n_levels()));
- for (unsigned int i=0; i<dofs_per_cell; ++i)
- {
- for (unsigned int j=0; j<dofs_per_cell; ++j)
- {
- if (flux_dof_mask(i,j) != DoFTools::none)
- {
- sparsity.add (dofs_on_other_cell[i],
- dofs_on_this_cell[j]);
- sparsity.add (dofs_on_other_cell[j],
- dofs_on_this_cell[i]);
- }
- }
- }
- }
- }
- }
-}
+ const unsigned int fine_dofs = dof.n_dofs(level);
+ const unsigned int coarse_dofs = dof.n_dofs(level-1);
+ // Matrix maps from fine level to coarse level
+ Assert (sparsity.n_rows() == coarse_dofs,
+ ExcDimensionMismatch (sparsity.n_rows(), coarse_dofs));
+ Assert (sparsity.n_cols() == fine_dofs,
+ ExcDimensionMismatch (sparsity.n_cols(), fine_dofs));
+ Assert (flux_mask.n_rows() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_rows(), n_comp));
+ Assert (flux_mask.n_cols() == n_comp,
+ ExcDimensionMismatch (flux_mask.n_cols(), n_comp));
-template <int dim, int spacedim>
-void
-MGTools::
-count_dofs_per_component (const MGDoFHandler<dim,spacedim> &dof_handler,
- std::vector<std::vector<unsigned int> > &result,
- bool only_once,
- std::vector<unsigned int> target_component)
-{
- const FiniteElement<dim>& fe = dof_handler.get_fe();
- const unsigned int n_components = fe.n_components();
- const unsigned int nlevels = dof_handler.get_tria().n_levels();
-
- Assert (result.size() == nlevels,
- ExcDimensionMismatch(result.size(), nlevels));
-
- if (target_component.size() == 0)
- {
- target_component.resize(n_components);
- for (unsigned int i=0;i<n_components;++i)
- target_component[i] = i;
- }
-
- Assert(target_component.size() == n_components,
- ExcDimensionMismatch(target_component.size(), n_components));
-
- for (unsigned int l=0;l<nlevels;++l)
- {
- result[l].resize (n_components);
- std::fill (result[l].begin(),result[l].end(), 0U);
-
- // special case for only one
- // component. treat this first
- // since it does not require any
- // computations
- if (n_components == 1)
- {
- result[l][0] = dof_handler.n_dofs(l);
- } else {
+ const unsigned int dofs_per_cell = dof.get_fe().dofs_per_cell;
+ std::vector<unsigned int> dofs_on_this_cell(dofs_per_cell);
+ std::vector<unsigned int> dofs_on_other_cell(dofs_per_cell);
+ Table<2,bool> support_on_face(dofs_per_cell, GeometryInfo<dim>::faces_per_cell);
+
+ typename MGDoFHandler<dim,spacedim>::cell_iterator cell = dof.begin(level),
+ endc = dof.end(level);
+
+ const Table<2,DoFTools::Coupling> flux_dof_mask
+ = DoFTools::dof_couplings_from_component_couplings(fe, flux_mask);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ for (unsigned int f=0; f<GeometryInfo<dim>::faces_per_cell;++f)
+ support_on_face(i,f) = fe.has_support_on_face(i,f);
+
+ for (; cell!=endc; ++cell)
+ {
+ cell->get_mg_dof_indices (dofs_on_this_cell);
+ // Loop over all interior neighbors
+ for (unsigned int face = 0;
+ face < GeometryInfo<dim>::faces_per_cell;
+ ++face)
+ {
+ // Neighbor is coarser
+
+ if ( (! cell->at_boundary(face)) &&
+ (static_cast<unsigned int>(cell->neighbor_level(face)) != level) )
+ {
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ neighbor = cell->neighbor(face);
+ neighbor->get_mg_dof_indices (dofs_on_other_cell);
+
+ for (unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ for (unsigned int j=0; j<dofs_per_cell; ++j)
+ {
+ if (flux_dof_mask(i,j) != DoFTools::none)
+ {
+ sparsity.add (dofs_on_other_cell[i],
+ dofs_on_this_cell[j]);
+ sparsity.add (dofs_on_other_cell[j],
+ dofs_on_this_cell[i]);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+
+ template <int dim, int spacedim>
+ void
+
+ count_dofs_per_component (const MGDoFHandler<dim,spacedim> &dof_handler,
+ std::vector<std::vector<unsigned int> > &result,
+ bool only_once,
+ std::vector<unsigned int> target_component)
+ {
+ const FiniteElement<dim>& fe = dof_handler.get_fe();
+ const unsigned int n_components = fe.n_components();
+ const unsigned int nlevels = dof_handler.get_tria().n_levels();
+
+ Assert (result.size() == nlevels,
+ ExcDimensionMismatch(result.size(), nlevels));
+
+ if (target_component.size() == 0)
+ {
+ target_component.resize(n_components);
+ for (unsigned int i=0;i<n_components;++i)
+ target_component[i] = i;
+ }
+
+ Assert(target_component.size() == n_components,
+ ExcDimensionMismatch(target_component.size(), n_components));
+
+ for (unsigned int l=0;l<nlevels;++l)
+ {
+ result[l].resize (n_components);
+ std::fill (result[l].begin(),result[l].end(), 0U);
+
+ // special case for only one
+ // component. treat this first
+ // since it does not require any
+ // computations
+ if (n_components == 1)
+ {
+ result[l][0] = dof_handler.n_dofs(l);
+ } else {
// otherwise determine the number
// of dofs in each component
// separately. do so in parallel
dof_handler.n_dofs(l),
ExcInternalError());
}
- }
-}
-
-
-
-template <int dim, int spacedim>
-void
-MGTools::
-count_dofs_per_component (const MGDoFHandler<dim,spacedim> &dof_handler,
- std::vector<std::vector<unsigned int> > &result,
- std::vector<unsigned int> target_component)
-{
- count_dofs_per_component (dof_handler, result,
- false, target_component);
-}
-
+ }
+ }
-template <int dim, int spacedim>
-void
-MGTools::count_dofs_per_block (
- const MGDoFHandler<dim,spacedim>& dof_handler,
- std::vector<std::vector<unsigned int> >& dofs_per_block,
- std::vector<unsigned int> target_block)
-{
- const FiniteElement<dim,spacedim>& fe = dof_handler.get_fe();
- const unsigned int n_blocks = fe.n_blocks();
- const unsigned int n_levels = dof_handler.get_tria().n_levels();
-
- AssertDimension (dofs_per_block.size(), n_levels);
-
- for (unsigned int l=0;l<n_levels;++l)
- std::fill (dofs_per_block[l].begin(), dofs_per_block[l].end(), 0U);
- // If the empty vector was given as
- // default argument, set up this
- // vector as identity.
- if (target_block.size()==0)
- {
- target_block.resize(n_blocks);
- for (unsigned int i=0;i<n_blocks;++i)
- target_block[i] = i;
- }
- Assert(target_block.size()==n_blocks,
- ExcDimensionMismatch(target_block.size(),n_blocks));
-
- const unsigned int max_block
- = *std::max_element (target_block.begin(),
- target_block.end());
- const unsigned int n_target_blocks = max_block + 1;
-
- for (unsigned int l=0;l<n_levels;++l)
- AssertDimension (dofs_per_block[l].size(), n_target_blocks);
-
- // special case for only one
- // block. treat this first
- // since it does not require any
- // computations
- if (n_blocks == 1)
- {
- for (unsigned int l=0;l<n_levels;++l)
- dofs_per_block[l][0] = dof_handler.n_dofs(l);
- return;
- }
- // otherwise determine the number
- // of dofs in each block
- // separately. do so in parallel
- for (unsigned int l=0;l<n_levels;++l)
- {
- std::vector<std::vector<bool> >
- dofs_in_block (n_blocks, std::vector<bool>(dof_handler.n_dofs(l), false));
- std::vector<std::vector<bool> >
- block_select (n_blocks, std::vector<bool>(n_blocks, false));
- Threads::TaskGroup<> tasks;
- for (unsigned int i=0; i<n_blocks; ++i)
- {
- void (*fun_ptr) (const unsigned int level,
- const MGDoFHandler<dim,spacedim>&,
- const std::vector<bool>&,
- std::vector<bool>&,
- bool)
- = &DoFTools::template extract_level_dofs<dim>;
- block_select[i][i] = true;
- tasks += Threads::new_task (fun_ptr,
- l, dof_handler, block_select[i],
- dofs_in_block[i], true);
- };
- tasks.join_all ();
-
- // next count what we got
- for (unsigned int block=0;block<fe.n_blocks();++block)
- dofs_per_block[l][target_block[block]]
- += std::count(dofs_in_block[block].begin(),
- dofs_in_block[block].end(),
- true);
- }
-}
+ template <int dim, int spacedim>
+ void
+ count_dofs_per_component (const MGDoFHandler<dim,spacedim> &dof_handler,
+ std::vector<std::vector<unsigned int> > &result,
+ std::vector<unsigned int> target_component)
+ {
+ count_dofs_per_component (dof_handler, result,
+ false, target_component);
+ }
-template <>
-void
-MGTools::make_boundary_list(
- const MGDoFHandler<1,1>&,
- const FunctionMap<1>::type&,
- std::vector<std::set<unsigned int> >&,
- const std::vector<bool>&)
-{
- Assert(false, ExcNotImplemented());
-}
+ template <int dim, int spacedim>
+ void
+ count_dofs_per_block (
+ const MGDoFHandler<dim,spacedim>& dof_handler,
+ std::vector<std::vector<unsigned int> >& dofs_per_block,
+ std::vector<unsigned int> target_block)
+ {
+ const FiniteElement<dim,spacedim>& fe = dof_handler.get_fe();
+ const unsigned int n_blocks = fe.n_blocks();
+ const unsigned int n_levels = dof_handler.get_tria().n_levels();
-template <>
-void
-MGTools::make_boundary_list(
- const MGDoFHandler<1,2>&,
- const FunctionMap<1>::type&,
- std::vector<std::set<unsigned int> >&,
- const std::vector<bool>&)
-{
- Assert(false, ExcNotImplemented());
-}
+ AssertDimension (dofs_per_block.size(), n_levels);
+ for (unsigned int l=0;l<n_levels;++l)
+ std::fill (dofs_per_block[l].begin(), dofs_per_block[l].end(), 0U);
+ // If the empty vector was given as
+ // default argument, set up this
+ // vector as identity.
+ if (target_block.size()==0)
+ {
+ target_block.resize(n_blocks);
+ for (unsigned int i=0;i<n_blocks;++i)
+ target_block[i] = i;
+ }
+ Assert(target_block.size()==n_blocks,
+ ExcDimensionMismatch(target_block.size(),n_blocks));
+
+ const unsigned int max_block
+ = *std::max_element (target_block.begin(),
+ target_block.end());
+ const unsigned int n_target_blocks = max_block + 1;
+
+ for (unsigned int l=0;l<n_levels;++l)
+ AssertDimension (dofs_per_block[l].size(), n_target_blocks);
+
+ // special case for only one
+ // block. treat this first
+ // since it does not require any
+ // computations
+ if (n_blocks == 1)
+ {
+ for (unsigned int l=0;l<n_levels;++l)
+ dofs_per_block[l][0] = dof_handler.n_dofs(l);
+ return;
+ }
+ // otherwise determine the number
+ // of dofs in each block
+ // separately. do so in parallel
+ for (unsigned int l=0;l<n_levels;++l)
+ {
+ std::vector<std::vector<bool> >
+ dofs_in_block (n_blocks, std::vector<bool>(dof_handler.n_dofs(l), false));
+ std::vector<std::vector<bool> >
+ block_select (n_blocks, std::vector<bool>(n_blocks, false));
+ Threads::TaskGroup<> tasks;
+ for (unsigned int i=0; i<n_blocks; ++i)
+ {
+ void (*fun_ptr) (const unsigned int level,
+ const MGDoFHandler<dim,spacedim>&,
+ const std::vector<bool>&,
+ std::vector<bool>&,
+ bool)
+ = &DoFTools::template extract_level_dofs<dim>;
+ block_select[i][i] = true;
+ tasks += Threads::new_task (fun_ptr,
+ l, dof_handler, block_select[i],
+ dofs_in_block[i], true);
+ };
+ tasks.join_all ();
+
+ // next count what we got
+ for (unsigned int block=0;block<fe.n_blocks();++block)
+ dofs_per_block[l][target_block[block]]
+ += std::count(dofs_in_block[block].begin(),
+ dofs_in_block[block].end(),
+ true);
+ }
+ }
+
+
+
+ template <>
+ void
+ make_boundary_list(
+ const MGDoFHandler<1,1>&,
+ const FunctionMap<1>::type&,
+ std::vector<std::set<unsigned int> >&,
+ const std::vector<bool>&)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+
+ template <>
+ void
+ make_boundary_list(
+ const MGDoFHandler<1,2>&,
+ const FunctionMap<1>::type&,
+ std::vector<std::set<unsigned int> >&,
+ const std::vector<bool>&)
+ {
+ Assert(false, ExcNotImplemented());
+ }
+
+
+
+ template <int dim, int spacedim>
+ void
+ make_boundary_list(
+ const MGDoFHandler<dim,spacedim>& dof,
+ const typename FunctionMap<dim>::type& function_map,
+ std::vector<std::set<unsigned int> >& boundary_indices,
+ const std::vector<bool>& component_mask)
+ {
+ // if for whatever reason we were
+ // passed an empty map, return
+ // immediately
+ if (function_map.size() == 0)
+ return;
+ const unsigned int n_levels = dof.get_tria().n_levels();
-template <int dim, int spacedim>
-void
-MGTools::make_boundary_list(
- const MGDoFHandler<dim,spacedim>& dof,
- const typename FunctionMap<dim>::type& function_map,
- std::vector<std::set<unsigned int> >& boundary_indices,
- const std::vector<bool>& component_mask)
-{
- // if for whatever reason we were
- // passed an empty map, return
- // immediately
- if (function_map.size() == 0)
- return;
- const unsigned int n_levels = dof.get_tria().n_levels();
+ const unsigned int n_components = DoFTools::n_components(dof);
+ const bool fe_is_system = (n_components != 1);
+ AssertDimension (boundary_indices.size(), n_levels);
- const unsigned int n_components = DoFTools::n_components(dof);
- const bool fe_is_system = (n_components != 1);
+ std::vector<unsigned int> local_dofs;
+ local_dofs.reserve (DoFTools::max_dofs_per_face(dof));
+ std::fill (local_dofs.begin (), local_dofs.end (),
+ DoFHandler<dim,spacedim>::invalid_dof_index);
- AssertDimension (boundary_indices.size(), n_levels);
-
- std::vector<unsigned int> local_dofs;
- local_dofs.reserve (DoFTools::max_dofs_per_face(dof));
- std::fill (local_dofs.begin (), local_dofs.end (),
- DoFHandler<dim,spacedim>::invalid_dof_index);
+ // First, deal with the simpler
+ // case when we have to identify
+ // all boundary dofs
+ if (component_mask.size() == 0)
+ {
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ cell = dof.begin(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
+ {
+ const FiniteElement<dim> &fe = cell->get_fe();
+ const unsigned int level = cell->level();
+ local_dofs.resize(fe.dofs_per_face);
- // First, deal with the simpler
- // case when we have to identify
- // all boundary dofs
- if (component_mask.size() == 0)
- {
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- cell = dof.begin(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- {
- const FiniteElement<dim> &fe = cell->get_fe();
- const unsigned int level = cell->level();
- local_dofs.resize(fe.dofs_per_face);
+ for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
+ ++face_no)
+ if (cell->at_boundary(face_no) == true)
+ {
+ const typename MGDoFHandler<dim,spacedim>::face_iterator
+ face = cell->face(face_no);
+ const unsigned char bi = face->boundary_indicator();
+ // Face is listed in
+ // boundary map
+ if (function_map.find(bi) != function_map.end())
+ {
+ face->get_mg_dof_indices(level, local_dofs);
+ for (unsigned int i=0;i<fe.dofs_per_face;++i)
+ boundary_indices[level].insert(local_dofs[i]);
+ }
+ }
+ }
+ }
+ else
+ {
+ Assert (std::count(component_mask.begin(), component_mask.end(), true) > 0,
+ ExcMessage("It's probably worthwhile to select at least one component."));
+ typename MGDoFHandler<dim,spacedim>::cell_iterator
+ cell = dof.begin(),
+ endc = dof.end();
+ for (; cell!=endc; ++cell)
for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
++face_no)
- if (cell->at_boundary(face_no) == true)
- {
- const typename MGDoFHandler<dim,spacedim>::face_iterator
- face = cell->face(face_no);
- const unsigned char bi = face->boundary_indicator();
- // Face is listed in
- // boundary map
- if (function_map.find(bi) != function_map.end())
- {
- face->get_mg_dof_indices(level, local_dofs);
- for (unsigned int i=0;i<fe.dofs_per_face;++i)
- boundary_indices[level].insert(local_dofs[i]);
- }
- }
- }
- }
- else
- {
- Assert (std::count(component_mask.begin(), component_mask.end(), true) > 0,
- ExcMessage("It's probably worthwhile to select at least one component."));
-
- typename MGDoFHandler<dim,spacedim>::cell_iterator
- cell = dof.begin(),
- endc = dof.end();
- for (; cell!=endc; ++cell)
- for (unsigned int face_no = 0; face_no < GeometryInfo<dim>::faces_per_cell;
- ++face_no)
- {
- if (cell->at_boundary(face_no) == false)
- continue;
-
- const FiniteElement<dim> &fe = cell->get_fe();
- const unsigned int level = cell->level();
+ {
+ if (cell->at_boundary(face_no) == false)
+ continue;
- // we can presently deal only with
- // primitive elements for boundary
- // values. this does not preclude
- // us using non-primitive elements
- // in components that we aren't
- // interested in, however. make
- // sure that all shape functions
- // that are non-zero for the
- // components we are interested in,
- // are in fact primitive
- for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
- {
- const std::vector<bool> &nonzero_component_array
- = cell->get_fe().get_nonzero_components (i);
- for (unsigned int c=0; c<n_components; ++c)
- if ((nonzero_component_array[c] == true)
- &&
- (component_mask[c] == true))
- Assert (cell->get_fe().is_primitive (i),
- ExcMessage ("This function can only deal with requested boundary "
- "values that correspond to primitive (scalar) base "
- "elements"));
- }
+ const FiniteElement<dim> &fe = cell->get_fe();
+ const unsigned int level = cell->level();
+
+ // we can presently deal only with
+ // primitive elements for boundary
+ // values. this does not preclude
+ // us using non-primitive elements
+ // in components that we aren't
+ // interested in, however. make
+ // sure that all shape functions
+ // that are non-zero for the
+ // components we are interested in,
+ // are in fact primitive
+ for (unsigned int i=0; i<cell->get_fe().dofs_per_cell; ++i)
+ {
+ const std::vector<bool> &nonzero_component_array
+ = cell->get_fe().get_nonzero_components (i);
+ for (unsigned int c=0; c<n_components; ++c)
+ if ((nonzero_component_array[c] == true)
+ &&
+ (component_mask[c] == true))
+ Assert (cell->get_fe().is_primitive (i),
+ ExcMessage ("This function can only deal with requested boundary "
+ "values that correspond to primitive (scalar) base "
+ "elements"));
+ }
- typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(face_no);
- const unsigned char boundary_component = face->boundary_indicator();
- if (function_map.find(boundary_component) != function_map.end())
- // face is of the right component
- {
- // get indices, physical location and
- // boundary values of dofs on this
- // face
- local_dofs.resize (fe.dofs_per_face);
- face->get_mg_dof_indices (level, local_dofs);
- if (fe_is_system)
- {
- // enter those dofs
- // into the list that
- // match the
- // component
- // signature. avoid
- // the usual
- // complication that
- // we can't just use
- // *_system_to_component_index
- // for non-primitive
- // FEs
- for (unsigned int i=0; i<local_dofs.size(); ++i)
- {
- unsigned int component;
- if (fe.is_primitive())
- component = fe.face_system_to_component_index(i).first;
- else
- {
- // non-primitive
- // case. make
- // sure that
- // this
- // particular
- // shape
- // function
- // _is_
- // primitive,
- // and get at
- // it's
- // component. use
- // usual
- // trick to
- // transfer
- // face dof
- // index to
- // cell dof
-
- // index
- const unsigned int cell_i
- = (dim == 1 ?
- i
- :
- (dim == 2 ?
- (i<2*fe.dofs_per_vertex ? i : i+2*fe.dofs_per_vertex)
- :
- (dim == 3 ?
- (i<4*fe.dofs_per_vertex ?
- i
+ typename MGDoFHandler<dim,spacedim>::face_iterator face = cell->face(face_no);
+ const unsigned char boundary_component = face->boundary_indicator();
+ if (function_map.find(boundary_component) != function_map.end())
+ // face is of the right component
+ {
+ // get indices, physical location and
+ // boundary values of dofs on this
+ // face
+ local_dofs.resize (fe.dofs_per_face);
+ face->get_mg_dof_indices (level, local_dofs);
+ if (fe_is_system)
+ {
+ // enter those dofs
+ // into the list that
+ // match the
+ // component
+ // signature. avoid
+ // the usual
+ // complication that
+ // we can't just use
+ // *_system_to_component_index
+ // for non-primitive
+ // FEs
+ for (unsigned int i=0; i<local_dofs.size(); ++i)
+ {
+ unsigned int component;
+ if (fe.is_primitive())
+ component = fe.face_system_to_component_index(i).first;
+ else
+ {
+ // non-primitive
+ // case. make
+ // sure that
+ // this
+ // particular
+ // shape
+ // function
+ // _is_
+ // primitive,
+ // and get at
+ // it's
+ // component. use
+ // usual
+ // trick to
+ // transfer
+ // face dof
+ // index to
+ // cell dof
+
+ // index
+ const unsigned int cell_i
+ = (dim == 1 ?
+ i
+ :
+ (dim == 2 ?
+ (i<2*fe.dofs_per_vertex ? i : i+2*fe.dofs_per_vertex)
:
- (i<4*fe.dofs_per_vertex+4*fe.dofs_per_line ?
- i+4*fe.dofs_per_vertex
+ (dim == 3 ?
+ (i<4*fe.dofs_per_vertex ?
+ i
+ :
+ (i<4*fe.dofs_per_vertex+4*fe.dofs_per_line ?
+ i+4*fe.dofs_per_vertex
+ :
+ i+4*fe.dofs_per_vertex+8*fe.dofs_per_line))
:
- i+4*fe.dofs_per_vertex+8*fe.dofs_per_line))
- :
- numbers::invalid_unsigned_int)));
- Assert (cell_i < fe.dofs_per_cell, ExcInternalError());
-
- // make sure
- // that if
- // this is
- // not a
- // primitive
- // shape function,
- // then all
- // the
- // corresponding
- // components
- // in the
- // mask are
- // not set
+ numbers::invalid_unsigned_int)));
+ Assert (cell_i < fe.dofs_per_cell, ExcInternalError());
+
+ // make sure
+ // that if
+ // this is
+ // not a
+ // primitive
+ // shape function,
+ // then all
+ // the
+ // corresponding
+ // components
+ // in the
+ // mask are
+ // not set
// if (!fe.is_primitive(cell_i))
// for (unsigned int c=0; c<n_components; ++c)
// if (fe.get_nonzero_components(cell_i)[c])
// components. if shape function is non-primitive, then we will ignore
// the result in the following anyway, otherwise there's only one
// non-zero component which we will use
- component = (std::find (fe.get_nonzero_components(cell_i).begin(),
- fe.get_nonzero_components(cell_i).end(),
- true)
- -
- fe.get_nonzero_components(cell_i).begin());
- }
-
- if (component_mask[component] == true)
- boundary_indices[level].insert(local_dofs[i]);
- }
- }
- else
- for (unsigned int i=0; i<local_dofs.size(); ++i)
- boundary_indices[level].insert(local_dofs[i]);
- }
- }
- }
-}
+ component = (std::find (fe.get_nonzero_components(cell_i).begin(),
+ fe.get_nonzero_components(cell_i).end(),
+ true)
+ -
+ fe.get_nonzero_components(cell_i).begin());
+ }
+
+ if (component_mask[component] == true)
+ boundary_indices[level].insert(local_dofs[i]);
+ }
+ }
+ else
+ for (unsigned int i=0; i<local_dofs.size(); ++i)
+ boundary_indices[level].insert(local_dofs[i]);
+ }
+ }
+ }
+ }
-template <int dim, int spacedim>
-void
-MGTools::
-make_boundary_list(const MGDoFHandler<dim,spacedim>& dof,
- const typename FunctionMap<dim>::type& function_map,
- std::vector<IndexSet>& boundary_indices,
- const std::vector<bool>& component_mask)
-{
- Assert (boundary_indices.size() == dof.get_tria().n_levels(),
- ExcDimensionMismatch (boundary_indices.size(),
- dof.get_tria().n_levels()));
-
- std::vector<std::set<unsigned int> >
- my_boundary_indices (dof.get_tria().n_levels());
- make_boundary_list (dof, function_map, my_boundary_indices, component_mask);
- for (unsigned int i=0; i<dof.get_tria().n_levels(); ++i)
- {
- boundary_indices[i] = IndexSet (dof.n_dofs(i));
- boundary_indices[i].add_indices (my_boundary_indices[i].begin(),
- my_boundary_indices[i].end());
- }
-}
+ template <int dim, int spacedim>
+ void
+ make_boundary_list(const MGDoFHandler<dim,spacedim>& dof,
+ const typename FunctionMap<dim>::type& function_map,
+ std::vector<IndexSet>& boundary_indices,
+ const std::vector<bool>& component_mask)
+ {
+ Assert (boundary_indices.size() == dof.get_tria().n_levels(),
+ ExcDimensionMismatch (boundary_indices.size(),
+ dof.get_tria().n_levels()));
+ std::vector<std::set<unsigned int> >
+ my_boundary_indices (dof.get_tria().n_levels());
+ make_boundary_list (dof, function_map, my_boundary_indices, component_mask);
+ for (unsigned int i=0; i<dof.get_tria().n_levels(); ++i)
+ {
+ boundary_indices[i] = IndexSet (dof.n_dofs(i));
+ boundary_indices[i].add_indices (my_boundary_indices[i].begin(),
+ my_boundary_indices[i].end());
+ }
+ }
-template <>
-void
-MGTools::
-extract_inner_interface_dofs (
- const MGDoFHandler<1,1>&,
- std::vector<std::vector<bool> > &,
- std::vector<std::vector<bool> > &)
-{
- Assert(false, ExcNotImplemented());
-}
-template <>
-void
-MGTools::
-extract_inner_interface_dofs (
- const MGDoFHandler<1,1>&,
- std::vector<std::vector<bool> > &)
-{
- Assert(false, ExcNotImplemented());
-}
+ template <int dim, int spacedim>
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs)
+ {
+ Assert (interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
+ ExcDimensionMismatch (interface_dofs.size(),
+ mg_dof_handler.get_tria().n_levels()));
+ for (unsigned int l=0; l<mg_dof_handler.get_tria().n_levels(); ++l)
+ {
+ Assert (interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
+ ExcDimensionMismatch (interface_dofs[l].size(),
+ mg_dof_handler.n_dofs(l)));
+ std::fill (interface_dofs[l].begin(),
+ interface_dofs[l].end(),
+ false);
+ }
-template <>
-void
-MGTools::
-extract_inner_interface_dofs (
- const MGDoFHandler<1,2>&,
- std::vector<std::vector<bool> > &,
- std::vector<std::vector<bool> > &)
-{
- Assert(false, ExcNotImplemented());
-}
+ const FiniteElement<dim,spacedim> &fe = mg_dof_handler.get_fe();
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int dofs_per_face = fe.dofs_per_face;
+ std::vector<unsigned int> local_dof_indices (dofs_per_cell);
+ std::vector<bool> cell_dofs(dofs_per_cell, false);
-template <>
-void
-MGTools::
-extract_inner_interface_dofs (
- const MGDoFHandler<1,2>&,
- std::vector<std::vector<bool> > &)
-{
- Assert(false, ExcNotImplemented());
-}
+ typename MGDoFHandler<dim>::cell_iterator cell = mg_dof_handler.begin(),
+ endc = mg_dof_handler.end();
+ for (; cell!=endc; ++cell)
+ {
+ std::fill (cell_dofs.begin(), cell_dofs.end(), false);
+ for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
+ {
+ const typename DoFHandler<dim,spacedim>::face_iterator face = cell->face(face_nr);
+ if (!face->at_boundary())
+ {
+ //interior face
+ const typename MGDoFHandler<dim>::cell_iterator
+ neighbor = cell->neighbor(face_nr);
-template <int dim, int spacedim>
-void
-MGTools::
-extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs)
-{
- Assert (interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
- ExcDimensionMismatch (interface_dofs.size(),
- mg_dof_handler.get_tria().n_levels()));
+ if (neighbor->level() < cell->level())
+ {
+ for (unsigned int j=0; j<dofs_per_face; ++j)
+ cell_dofs[fe.face_to_cell_index(j,face_nr)] = true;
- for (unsigned int l=0; l<mg_dof_handler.get_tria().n_levels(); ++l)
- {
- Assert (interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
- ExcDimensionMismatch (interface_dofs[l].size(),
- mg_dof_handler.n_dofs(l)));
+ }
+ }
+ }
- std::fill (interface_dofs[l].begin(),
- interface_dofs[l].end(),
- false);
- }
+ const unsigned int level = cell->level();
+ cell->get_mg_dof_indices (local_dof_indices);
- const FiniteElement<dim,spacedim> &fe = mg_dof_handler.get_fe();
+ for(unsigned int i=0; i<dofs_per_cell; ++i)
+ if (cell_dofs[i])
+ interface_dofs[level][local_dof_indices[i]] = true;
+ }
+ }
- const unsigned int dofs_per_cell = fe.dofs_per_cell;
- const unsigned int dofs_per_face = fe.dofs_per_face;
- std::vector<unsigned int> local_dof_indices (dofs_per_cell);
- std::vector<bool> cell_dofs(dofs_per_cell, false);
- typename MGDoFHandler<dim>::cell_iterator cell = mg_dof_handler.begin(),
- endc = mg_dof_handler.end();
+ template <int dim, int spacedim>
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs,
+ std::vector<std::vector<bool> > &boundary_interface_dofs)
+ {
+ Assert (interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
+ ExcDimensionMismatch (interface_dofs.size(),
+ mg_dof_handler.get_tria().n_levels()));
+ Assert (boundary_interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
+ ExcDimensionMismatch (boundary_interface_dofs.size(),
+ mg_dof_handler.get_tria().n_levels()));
- for (; cell!=endc; ++cell)
- {
- std::fill (cell_dofs.begin(), cell_dofs.end(), false);
+ for (unsigned int l=0; l<mg_dof_handler.get_tria().n_levels(); ++l)
+ {
+ Assert (interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
+ ExcDimensionMismatch (interface_dofs[l].size(),
+ mg_dof_handler.n_dofs(l)));
+ Assert (boundary_interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
+ ExcDimensionMismatch (boundary_interface_dofs[l].size(),
+ mg_dof_handler.n_dofs(l)));
+
+ std::fill (interface_dofs[l].begin(),
+ interface_dofs[l].end(),
+ false);
+ std::fill (boundary_interface_dofs[l].begin(),
+ boundary_interface_dofs[l].end(),
+ false);
+ }
- for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
- {
- const typename DoFHandler<dim,spacedim>::face_iterator face = cell->face(face_nr);
- if (!face->at_boundary())
- {
- //interior face
- const typename MGDoFHandler<dim>::cell_iterator
- neighbor = cell->neighbor(face_nr);
+ const FiniteElement<dim,spacedim> &fe = mg_dof_handler.get_fe();
- if (neighbor->level() < cell->level())
- {
- for (unsigned int j=0; j<dofs_per_face; ++j)
- cell_dofs[fe.face_to_cell_index(j,face_nr)] = true;
+ const unsigned int dofs_per_cell = fe.dofs_per_cell;
+ const unsigned int dofs_per_face = fe.dofs_per_face;
- }
- }
- }
+ std::vector<unsigned int> local_dof_indices (dofs_per_cell);
+ std::vector<unsigned int> face_dof_indices (dofs_per_face);
- const unsigned int level = cell->level();
- cell->get_mg_dof_indices (local_dof_indices);
+ std::vector<bool> cell_dofs(dofs_per_cell, false);
+ std::vector<bool> boundary_cell_dofs(dofs_per_cell, false);
- for(unsigned int i=0; i<dofs_per_cell; ++i)
- if (cell_dofs[i])
- interface_dofs[level][local_dof_indices[i]] = true;
- }
-}
+ typename MGDoFHandler<dim>::cell_iterator cell = mg_dof_handler.begin(),
+ endc = mg_dof_handler.end();
+ for (; cell!=endc; ++cell)
+ {
+ bool has_coarser_neighbor = false;
+ std::fill (cell_dofs.begin(), cell_dofs.end(), false);
+ std::fill (boundary_cell_dofs.begin(), boundary_cell_dofs.end(), false);
-template <int dim, int spacedim>
-void
-MGTools::
-extract_inner_interface_dofs (const MGDoFHandler<dim,spacedim> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs,
- std::vector<std::vector<bool> > &boundary_interface_dofs)
-{
- Assert (interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
- ExcDimensionMismatch (interface_dofs.size(),
- mg_dof_handler.get_tria().n_levels()));
- Assert (boundary_interface_dofs.size() == mg_dof_handler.get_tria().n_levels(),
- ExcDimensionMismatch (boundary_interface_dofs.size(),
- mg_dof_handler.get_tria().n_levels()));
-
- for (unsigned int l=0; l<mg_dof_handler.get_tria().n_levels(); ++l)
- {
- Assert (interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
- ExcDimensionMismatch (interface_dofs[l].size(),
- mg_dof_handler.n_dofs(l)));
- Assert (boundary_interface_dofs[l].size() == mg_dof_handler.n_dofs(l),
- ExcDimensionMismatch (boundary_interface_dofs[l].size(),
- mg_dof_handler.n_dofs(l)));
-
- std::fill (interface_dofs[l].begin(),
- interface_dofs[l].end(),
- false);
- std::fill (boundary_interface_dofs[l].begin(),
- boundary_interface_dofs[l].end(),
- false);
- }
-
- const FiniteElement<dim,spacedim> &fe = mg_dof_handler.get_fe();
-
- const unsigned int dofs_per_cell = fe.dofs_per_cell;
- const unsigned int dofs_per_face = fe.dofs_per_face;
-
- std::vector<unsigned int> local_dof_indices (dofs_per_cell);
- std::vector<unsigned int> face_dof_indices (dofs_per_face);
-
- std::vector<bool> cell_dofs(dofs_per_cell, false);
- std::vector<bool> boundary_cell_dofs(dofs_per_cell, false);
-
- typename MGDoFHandler<dim>::cell_iterator cell = mg_dof_handler.begin(),
- endc = mg_dof_handler.end();
-
- for (; cell!=endc; ++cell)
- {
- bool has_coarser_neighbor = false;
-
- std::fill (cell_dofs.begin(), cell_dofs.end(), false);
- std::fill (boundary_cell_dofs.begin(), boundary_cell_dofs.end(), false);
-
- for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
- {
- const typename DoFHandler<dim,spacedim>::face_iterator face = cell->face(face_nr);
- if (!face->at_boundary())
- {
- //interior face
- const typename MGDoFHandler<dim>::cell_iterator
- neighbor = cell->neighbor(face_nr);
+ for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
+ {
+ const typename DoFHandler<dim,spacedim>::face_iterator face = cell->face(face_nr);
+ if (!face->at_boundary())
+ {
+ //interior face
+ const typename MGDoFHandler<dim>::cell_iterator
+ neighbor = cell->neighbor(face_nr);
- // Do refinement face
- // from the coarse side
- if (neighbor->level() < cell->level())
- {
- for (unsigned int j=0; j<dofs_per_face; ++j)
+ // Do refinement face
+ // from the coarse side
+ if (neighbor->level() < cell->level())
+ {
+ for (unsigned int j=0; j<dofs_per_face; ++j)
cell_dofs[fe.face_to_cell_index(j,face_nr)] = true;
- has_coarser_neighbor = true;
- }
- }
- }
+ has_coarser_neighbor = true;
+ }
+ }
+ }
- if (has_coarser_neighbor == true)
- for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
- if(cell->at_boundary(face_nr))
- for(unsigned int j=0; j<dofs_per_face; ++j)
+ if (has_coarser_neighbor == true)
+ for (unsigned int face_nr=0; face_nr<GeometryInfo<dim>::faces_per_cell; ++face_nr)
+ if(cell->at_boundary(face_nr))
+ for(unsigned int j=0; j<dofs_per_face; ++j)
// if (cell_dofs[fe.face_to_cell_index(j,face_nr)] == true) //is this necessary?
boundary_cell_dofs[fe.face_to_cell_index(j,face_nr)] = true;
- const unsigned int level = cell->level();
- cell->get_mg_dof_indices (local_dof_indices);
+ const unsigned int level = cell->level();
+ cell->get_mg_dof_indices (local_dof_indices);
- for(unsigned int i=0; i<dofs_per_cell; ++i)
- {
- if (cell_dofs[i])
- interface_dofs[level][local_dof_indices[i]] = true;
+ for(unsigned int i=0; i<dofs_per_cell; ++i)
+ {
+ if (cell_dofs[i])
+ interface_dofs[level][local_dof_indices[i]] = true;
- if (boundary_cell_dofs[i])
- boundary_interface_dofs[level][local_dof_indices[i]] = true;
- }
- }
-}
+ if (boundary_cell_dofs[i])
+ boundary_interface_dofs[level][local_dof_indices[i]] = true;
+ }
+ }
+ }
-template <typename number>
-void
-MGTools::apply_boundary_values (
- const std::set<unsigned int> &boundary_dofs,
- SparseMatrix<number>& matrix,
- const bool preserve_symmetry,
- const bool ignore_zeros)
-{
- // if no boundary values are to be applied
- // simply return
- if (boundary_dofs.size() == 0)
- return;
-
-
- const unsigned int n_dofs = matrix.m();
-
- // if a diagonal entry is zero
- // later, then we use another
- // number instead. take it to be
- // the first nonzero diagonal
- // element of the matrix, or 1 if
- // there is no such thing
- number first_nonzero_diagonal_entry = 1;
- for (unsigned int i=0; i<n_dofs; ++i)
- if (matrix.diag_element(i) != 0)
- {
- first_nonzero_diagonal_entry = matrix.diag_element(i);
- break;
- }
+ template <typename number>
+ void
+ apply_boundary_values (
+ const std::set<unsigned int> &boundary_dofs,
+ SparseMatrix<number>& matrix,
+ const bool preserve_symmetry,
+ const bool ignore_zeros)
+ {
+ // if no boundary values are to be applied
+ // simply return
+ if (boundary_dofs.size() == 0)
+ return;
+
+ const unsigned int n_dofs = matrix.m();
- std::set<unsigned int>::const_iterator dof = boundary_dofs.begin(),
- endd = boundary_dofs.end();
- const SparsityPattern &sparsity = matrix.get_sparsity_pattern();
- const std::size_t *sparsity_rowstart = sparsity.get_rowstart_indices();
- const unsigned int *sparsity_colnums = sparsity.get_column_numbers();
- for (; dof != endd; ++dof)
- {
- Assert (*dof < n_dofs, ExcInternalError());
-
- const unsigned int dof_number = *dof;
- // for each boundary dof:
-
- // set entries of this line
- // to zero except for the diagonal
- // entry. Note that the diagonal
- // entry is always the first one
- // for square matrices, i.e.
- // we shall not set
- // matrix.global_entry(
- // sparsity_rowstart[dof.first])
- const unsigned int last = sparsity_rowstart[dof_number+1];
- for (unsigned int j=sparsity_rowstart[dof_number]+1; j<last; ++j)
- matrix.global_entry(j) = 0.;
-
-
- // set right hand side to
- // wanted value: if main diagonal
- // entry nonzero, don't touch it
- // and scale rhs accordingly. If
- // zero, take the first main
- // diagonal entry we can find, or
- // one if no nonzero main diagonal
- // element exists. Normally, however,
- // the main diagonal entry should
- // not be zero.
- //
- // store the new rhs entry to make
- // the gauss step more efficient
- if(!ignore_zeros)
- matrix.set (dof_number, dof_number,
- first_nonzero_diagonal_entry);
- // if the user wants to have
- // the symmetry of the matrix
- // preserved, and if the
- // sparsity pattern is
- // symmetric, then do a Gauss
- // elimination step with the
- // present row
- if (preserve_symmetry)
+ // if a diagonal entry is zero
+ // later, then we use another
+ // number instead. take it to be
+ // the first nonzero diagonal
+ // element of the matrix, or 1 if
+ // there is no such thing
+ number first_nonzero_diagonal_entry = 1;
+ for (unsigned int i=0; i<n_dofs; ++i)
+ if (matrix.diag_element(i) != 0)
{
- // we have to loop over all
- // rows of the matrix which
- // have a nonzero entry in
- // the column which we work
- // in presently. if the
- // sparsity pattern is
- // symmetric, then we can
- // get the positions of
- // these rows cheaply by
- // looking at the nonzero
- // column numbers of the
- // present row. we need not
- // look at the first entry,
- // since that is the
- // diagonal element and
- // thus the present row
- for (unsigned int j=sparsity_rowstart[dof_number]+1; j<last; ++j)
- {
- const unsigned int row = sparsity_colnums[j];
-
- // find the position of
- // element
- // (row,dof_number)
- const unsigned int *
- p = Utilities::lower_bound(&sparsity_colnums[sparsity_rowstart[row]+1],
- &sparsity_colnums[sparsity_rowstart[row+1]],
- dof_number);
-
- // check whether this line has
- // an entry in the regarding column
- // (check for ==dof_number and
- // != next_row, since if
- // row==dof_number-1, *p is a
- // past-the-end pointer but points
- // to dof_number anyway...)
- //
- // there should be such an entry!
- Assert ((*p == dof_number) &&
- (p != &sparsity_colnums[sparsity_rowstart[row+1]]),
- ExcInternalError());
-
- const unsigned int global_entry
- = (p - &sparsity_colnums[sparsity_rowstart[0]]);
-
- // correct right hand side
- // set matrix entry to zero
- matrix.global_entry(global_entry) = 0.;
- }
+ first_nonzero_diagonal_entry = matrix.diag_element(i);
+ break;
}
- }
-}
-
-template <typename number>
-void
-MGTools::apply_boundary_values (
- const std::set<unsigned int>& boundary_dofs,
- BlockSparseMatrix<number>& matrix,
- const bool preserve_symmetry)
-{
- const unsigned int blocks = matrix.n_block_rows();
-
- Assert (matrix.n_block_rows() == matrix.n_block_cols(),
- ExcNotQuadratic());
- Assert (matrix.get_sparsity_pattern().get_row_indices() ==
- matrix.get_sparsity_pattern().get_column_indices(),
- ExcNotQuadratic());
-
- for (unsigned int i=0; i<blocks; ++i)
- Assert (matrix.block(i,i).get_sparsity_pattern().optimize_diagonal(),
- SparsityPattern::ExcDiagonalNotOptimized());
-
-
- // if no boundary values are to be applied
- // simply return
- if (boundary_dofs.size() == 0)
- return;
-
-
- const unsigned int n_dofs = matrix.m();
-
- // if a diagonal entry is zero
- // later, then we use another
- // number instead. take it to be
- // the first nonzero diagonal
- // element of the matrix, or 1 if
- // there is no such thing
- number first_nonzero_diagonal_entry = 0;
- for (unsigned int diag_block=0; diag_block<blocks; ++diag_block)
- {
- for (unsigned int i=0; i<matrix.block(diag_block,diag_block).n(); ++i)
- if (matrix.block(diag_block,diag_block).diag_element(i) != 0)
+ std::set<unsigned int>::const_iterator dof = boundary_dofs.begin(),
+ endd = boundary_dofs.end();
+ const SparsityPattern &sparsity = matrix.get_sparsity_pattern();
+ const std::size_t *sparsity_rowstart = sparsity.get_rowstart_indices();
+ const unsigned int *sparsity_colnums = sparsity.get_column_numbers();
+ for (; dof != endd; ++dof)
+ {
+ Assert (*dof < n_dofs, ExcInternalError());
+
+ const unsigned int dof_number = *dof;
+ // for each boundary dof:
+
+ // set entries of this line
+ // to zero except for the diagonal
+ // entry. Note that the diagonal
+ // entry is always the first one
+ // for square matrices, i.e.
+ // we shall not set
+ // matrix.global_entry(
+ // sparsity_rowstart[dof.first])
+ const unsigned int last = sparsity_rowstart[dof_number+1];
+ for (unsigned int j=sparsity_rowstart[dof_number]+1; j<last; ++j)
+ matrix.global_entry(j) = 0.;
+
+
+ // set right hand side to
+ // wanted value: if main diagonal
+ // entry nonzero, don't touch it
+ // and scale rhs accordingly. If
+ // zero, take the first main
+ // diagonal entry we can find, or
+ // one if no nonzero main diagonal
+ // element exists. Normally, however,
+ // the main diagonal entry should
+ // not be zero.
+ //
+ // store the new rhs entry to make
+ // the gauss step more efficient
+ if(!ignore_zeros)
+ matrix.set (dof_number, dof_number,
+ first_nonzero_diagonal_entry);
+ // if the user wants to have
+ // the symmetry of the matrix
+ // preserved, and if the
+ // sparsity pattern is
+ // symmetric, then do a Gauss
+ // elimination step with the
+ // present row
+ if (preserve_symmetry)
{
- first_nonzero_diagonal_entry
- = matrix.block(diag_block,diag_block).diag_element(i);
- break;
+ // we have to loop over all
+ // rows of the matrix which
+ // have a nonzero entry in
+ // the column which we work
+ // in presently. if the
+ // sparsity pattern is
+ // symmetric, then we can
+ // get the positions of
+ // these rows cheaply by
+ // looking at the nonzero
+ // column numbers of the
+ // present row. we need not
+ // look at the first entry,
+ // since that is the
+ // diagonal element and
+ // thus the present row
+ for (unsigned int j=sparsity_rowstart[dof_number]+1; j<last; ++j)
+ {
+ const unsigned int row = sparsity_colnums[j];
+
+ // find the position of
+ // element
+ // (row,dof_number)
+ const unsigned int *
+ p = Utilities::lower_bound(&sparsity_colnums[sparsity_rowstart[row]+1],
+ &sparsity_colnums[sparsity_rowstart[row+1]],
+ dof_number);
+
+ // check whether this line has
+ // an entry in the regarding column
+ // (check for ==dof_number and
+ // != next_row, since if
+ // row==dof_number-1, *p is a
+ // past-the-end pointer but points
+ // to dof_number anyway...)
+ //
+ // there should be such an entry!
+ Assert ((*p == dof_number) &&
+ (p != &sparsity_colnums[sparsity_rowstart[row+1]]),
+ ExcInternalError());
+
+ const unsigned int global_entry
+ = (p - &sparsity_colnums[sparsity_rowstart[0]]);
+
+ // correct right hand side
+ // set matrix entry to zero
+ matrix.global_entry(global_entry) = 0.;
+ }
}
- // check whether we have found
- // something in the present
- // block
- if (first_nonzero_diagonal_entry != 0)
- break;
- }
- // nothing found on all diagonal
- // blocks? if so, use 1.0 instead
- if (first_nonzero_diagonal_entry == 0)
- first_nonzero_diagonal_entry = 1;
-
-
- std::set<unsigned int>::const_iterator dof = boundary_dofs.begin(),
- endd = boundary_dofs.end();
- const BlockSparsityPattern &
- sparsity_pattern = matrix.get_sparsity_pattern();
-
- // pointer to the mapping between
- // global and block indices. since
- // the row and column mappings are
- // equal, store a pointer on only
- // one of them
- const BlockIndices &
- index_mapping = sparsity_pattern.get_column_indices();
-
- // now loop over all boundary dofs
- for (; dof != endd; ++dof)
- {
- Assert (*dof < n_dofs, ExcInternalError());
-
- // get global index and index
- // in the block in which this
- // dof is located
- const unsigned int dof_number = *dof;
- const std::pair<unsigned int,unsigned int>
- block_index = index_mapping.global_to_local (dof_number);
-
- // for each boundary dof:
-
- // set entries of this line
- // to zero except for the diagonal
- // entry. Note that the diagonal
- // entry is always the first one
- // for square matrices, i.e.
- // we shall not set
- // matrix.global_entry(
- // sparsity_rowstart[dof.first])
- // of the diagonal block
- for (unsigned int block_col=0; block_col<blocks; ++block_col)
- {
- const SparsityPattern &
- local_sparsity = sparsity_pattern.block(block_index.first,
- block_col);
-
- // find first and last
- // entry in the present row
- // of the present
- // block. exclude the main
- // diagonal element, which
- // is the diagonal element
- // of a diagonal block,
- // which must be a square
- // matrix so the diagonal
- // element is the first of
- // this row.
- const unsigned int
- last = local_sparsity.get_rowstart_indices()[block_index.second+1],
- first = (block_col == block_index.first ?
- local_sparsity.get_rowstart_indices()[block_index.second]+1 :
- local_sparsity.get_rowstart_indices()[block_index.second]);
-
- for (unsigned int j=first; j<last; ++j)
- matrix.block(block_index.first,block_col).global_entry(j) = 0.;
- }
+ }
+ }
- matrix.block(block_index.first, block_index.first)
- .diag_element(block_index.second)
- = first_nonzero_diagonal_entry;
-
- // if the user wants to have
- // the symmetry of the matrix
- // preserved, and if the
- // sparsity pattern is
- // symmetric, then do a Gauss
- // elimination step with the
- // present row. this is a
- // little more complicated for
- // block matrices.
- if (preserve_symmetry)
- {
- // we have to loop over all
- // rows of the matrix which
- // have a nonzero entry in
- // the column which we work
- // in presently. if the
- // sparsity pattern is
- // symmetric, then we can
- // get the positions of
- // these rows cheaply by
- // looking at the nonzero
- // column numbers of the
- // present row.
- //
- // note that if we check
- // whether row @p{row} in
- // block (r,c) is non-zero,
- // then we have to check
- // for the existence of
- // column @p{row} in block
- // (c,r), i.e. of the
- // transpose block
- for (unsigned int block_row=0; block_row<blocks; ++block_row)
+
+
+ template <typename number>
+ void
+ apply_boundary_values (
+ const std::set<unsigned int>& boundary_dofs,
+ BlockSparseMatrix<number>& matrix,
+ const bool preserve_symmetry)
+ {
+ const unsigned int blocks = matrix.n_block_rows();
+
+ Assert (matrix.n_block_rows() == matrix.n_block_cols(),
+ ExcNotQuadratic());
+ Assert (matrix.get_sparsity_pattern().get_row_indices() ==
+ matrix.get_sparsity_pattern().get_column_indices(),
+ ExcNotQuadratic());
+
+ for (unsigned int i=0; i<blocks; ++i)
+ Assert (matrix.block(i,i).get_sparsity_pattern().optimize_diagonal(),
+ SparsityPattern::ExcDiagonalNotOptimized());
+
+
+ // if no boundary values are to be applied
+ // simply return
+ if (boundary_dofs.size() == 0)
+ return;
+
+
+ const unsigned int n_dofs = matrix.m();
+
+ // if a diagonal entry is zero
+ // later, then we use another
+ // number instead. take it to be
+ // the first nonzero diagonal
+ // element of the matrix, or 1 if
+ // there is no such thing
+ number first_nonzero_diagonal_entry = 0;
+ for (unsigned int diag_block=0; diag_block<blocks; ++diag_block)
+ {
+ for (unsigned int i=0; i<matrix.block(diag_block,diag_block).n(); ++i)
+ if (matrix.block(diag_block,diag_block).diag_element(i) != 0)
{
- // get pointers to the
- // sparsity patterns of
- // this block and of
- // the transpose one
- const SparsityPattern &this_sparsity
- = sparsity_pattern.block (block_row, block_index.first);
- const SparsityPattern &transpose_sparsity
- = sparsity_pattern.block (block_index.first, block_row);
-
- // traverse the row of
- // the transpose block
- // to find the
- // interesting rows in
- // the present block.
- // don't use the
- // diagonal element of
- // the diagonal block
- const unsigned int
- first = (block_index.first == block_row ?
- transpose_sparsity.get_rowstart_indices()[block_index.second]+1 :
- transpose_sparsity.get_rowstart_indices()[block_index.second]),
- last = transpose_sparsity.get_rowstart_indices()[block_index.second+1];
-
- for (unsigned int j=first; j<last; ++j)
- {
- // get the number
- // of the column in
- // this row in
- // which a nonzero
- // entry is. this
- // is also the row
- // of the transpose
- // block which has
- // an entry in the
- // interesting row
- const unsigned int row = transpose_sparsity.get_column_numbers()[j];
-
- // find the
- // position of
- // element
- // (row,dof_number)
- // in this block
- // (not in the
- // transpose
- // one). note that
- // we have to take
- // care of special
- // cases with
- // square
- // sub-matrices
- const unsigned int *p = 0;
- if (this_sparsity.n_rows() == this_sparsity.n_cols())
- {
- if (this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row]]
- ==
- block_index.second)
- p = &this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row]];
- else
- p = Utilities::lower_bound(&this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row]+1],
- &this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row+1]],
- block_index.second);
- }
- else
- p = Utilities::lower_bound(&this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row]],
- &this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row+1]],
- block_index.second);
-
- // check whether this line has
- // an entry in the regarding column
- // (check for ==dof_number and
- // != next_row, since if
- // row==dof_number-1, *p is a
- // past-the-end pointer but points
- // to dof_number anyway...)
- //
- // there should be
- // such an entry!
- // note, however,
- // that this
- // assertion will
- // fail sometimes
- // if the sparsity
- // pattern is not
- // symmetric!
- Assert ((*p == block_index.second) &&
- (p != &this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[row+1]]),
- ExcInternalError());
-
- const unsigned int global_entry
- = (p
- -
- &this_sparsity.get_column_numbers()
- [this_sparsity.get_rowstart_indices()[0]]);
-
- // set matrix entry to zero
- matrix.block(block_row,block_index.first).global_entry(global_entry) = 0.;
- }
+ first_nonzero_diagonal_entry
+ = matrix.block(diag_block,diag_block).diag_element(i);
+ break;
}
- }
- }
-}
+ // check whether we have found
+ // something in the present
+ // block
+ if (first_nonzero_diagonal_entry != 0)
+ break;
+ }
+ // nothing found on all diagonal
+ // blocks? if so, use 1.0 instead
+ if (first_nonzero_diagonal_entry == 0)
+ first_nonzero_diagonal_entry = 1;
+
+
+ std::set<unsigned int>::const_iterator dof = boundary_dofs.begin(),
+ endd = boundary_dofs.end();
+ const BlockSparsityPattern &
+ sparsity_pattern = matrix.get_sparsity_pattern();
+
+ // pointer to the mapping between
+ // global and block indices. since
+ // the row and column mappings are
+ // equal, store a pointer on only
+ // one of them
+ const BlockIndices &
+ index_mapping = sparsity_pattern.get_column_indices();
+
+ // now loop over all boundary dofs
+ for (; dof != endd; ++dof)
+ {
+ Assert (*dof < n_dofs, ExcInternalError());
+
+ // get global index and index
+ // in the block in which this
+ // dof is located
+ const unsigned int dof_number = *dof;
+ const std::pair<unsigned int,unsigned int>
+ block_index = index_mapping.global_to_local (dof_number);
+
+ // for each boundary dof:
+
+ // set entries of this line
+ // to zero except for the diagonal
+ // entry. Note that the diagonal
+ // entry is always the first one
+ // for square matrices, i.e.
+ // we shall not set
+ // matrix.global_entry(
+ // sparsity_rowstart[dof.first])
+ // of the diagonal block
+ for (unsigned int block_col=0; block_col<blocks; ++block_col)
+ {
+ const SparsityPattern &
+ local_sparsity = sparsity_pattern.block(block_index.first,
+ block_col);
+
+ // find first and last
+ // entry in the present row
+ // of the present
+ // block. exclude the main
+ // diagonal element, which
+ // is the diagonal element
+ // of a diagonal block,
+ // which must be a square
+ // matrix so the diagonal
+ // element is the first of
+ // this row.
+ const unsigned int
+ last = local_sparsity.get_rowstart_indices()[block_index.second+1],
+ first = (block_col == block_index.first ?
+ local_sparsity.get_rowstart_indices()[block_index.second]+1 :
+ local_sparsity.get_rowstart_indices()[block_index.second]);
+
+ for (unsigned int j=first; j<last; ++j)
+ matrix.block(block_index.first,block_col).global_entry(j) = 0.;
+ }
+ matrix.block(block_index.first, block_index.first)
+ .diag_element(block_index.second)
+ = first_nonzero_diagonal_entry;
+
+ // if the user wants to have
+ // the symmetry of the matrix
+ // preserved, and if the
+ // sparsity pattern is
+ // symmetric, then do a Gauss
+ // elimination step with the
+ // present row. this is a
+ // little more complicated for
+ // block matrices.
+ if (preserve_symmetry)
+ {
+ // we have to loop over all
+ // rows of the matrix which
+ // have a nonzero entry in
+ // the column which we work
+ // in presently. if the
+ // sparsity pattern is
+ // symmetric, then we can
+ // get the positions of
+ // these rows cheaply by
+ // looking at the nonzero
+ // column numbers of the
+ // present row.
+ //
+ // note that if we check
+ // whether row @p{row} in
+ // block (r,c) is non-zero,
+ // then we have to check
+ // for the existence of
+ // column @p{row} in block
+ // (c,r), i.e. of the
+ // transpose block
+ for (unsigned int block_row=0; block_row<blocks; ++block_row)
+ {
+ // get pointers to the
+ // sparsity patterns of
+ // this block and of
+ // the transpose one
+ const SparsityPattern &this_sparsity
+ = sparsity_pattern.block (block_row, block_index.first);
+ const SparsityPattern &transpose_sparsity
+ = sparsity_pattern.block (block_index.first, block_row);
+
+ // traverse the row of
+ // the transpose block
+ // to find the
+ // interesting rows in
+ // the present block.
+ // don't use the
+ // diagonal element of
+ // the diagonal block
+ const unsigned int
+ first = (block_index.first == block_row ?
+ transpose_sparsity.get_rowstart_indices()[block_index.second]+1 :
+ transpose_sparsity.get_rowstart_indices()[block_index.second]),
+ last = transpose_sparsity.get_rowstart_indices()[block_index.second+1];
+
+ for (unsigned int j=first; j<last; ++j)
+ {
+ // get the number
+ // of the column in
+ // this row in
+ // which a nonzero
+ // entry is. this
+ // is also the row
+ // of the transpose
+ // block which has
+ // an entry in the
+ // interesting row
+ const unsigned int row = transpose_sparsity.get_column_numbers()[j];
+
+ // find the
+ // position of
+ // element
+ // (row,dof_number)
+ // in this block
+ // (not in the
+ // transpose
+ // one). note that
+ // we have to take
+ // care of special
+ // cases with
+ // square
+ // sub-matrices
+ const unsigned int *p = 0;
+ if (this_sparsity.n_rows() == this_sparsity.n_cols())
+ {
+ if (this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row]]
+ ==
+ block_index.second)
+ p = &this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row]];
+ else
+ p = Utilities::lower_bound(&this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row]+1],
+ &this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row+1]],
+ block_index.second);
+ }
+ else
+ p = Utilities::lower_bound(&this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row]],
+ &this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row+1]],
+ block_index.second);
+
+ // check whether this line has
+ // an entry in the regarding column
+ // (check for ==dof_number and
+ // != next_row, since if
+ // row==dof_number-1, *p is a
+ // past-the-end pointer but points
+ // to dof_number anyway...)
+ //
+ // there should be
+ // such an entry!
+ // note, however,
+ // that this
+ // assertion will
+ // fail sometimes
+ // if the sparsity
+ // pattern is not
+ // symmetric!
+ Assert ((*p == block_index.second) &&
+ (p != &this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[row+1]]),
+ ExcInternalError());
+
+ const unsigned int global_entry
+ = (p
+ -
+ &this_sparsity.get_column_numbers()
+ [this_sparsity.get_rowstart_indices()[0]]);
+
+ // set matrix entry to zero
+ matrix.block(block_row,block_index.first).global_entry(global_entry) = 0.;
+ }
+ }
+ }
+ }
+ }
+}
// explicit instantiations
#include "mg_tools.inst"
-template void MGTools::apply_boundary_values (
- const std::set<unsigned int>&,
- SparseMatrix<float>&, const bool, const bool);
-template void MGTools::apply_boundary_values (
- const std::set<unsigned int>&,
- SparseMatrix<double>&, const bool, const bool);
-template void MGTools::apply_boundary_values (
- const std::set<unsigned int>&,
- BlockSparseMatrix<float>&, const bool);
-template void MGTools::apply_boundary_values (
- const std::set<unsigned int>&,
- BlockSparseMatrix<double>&, const bool);
+namespace MGTools
+{
+ template void apply_boundary_values (
+ const std::set<unsigned int>&,
+ SparseMatrix<float>&, const bool, const bool);
+ template void apply_boundary_values (
+ const std::set<unsigned int>&,
+ SparseMatrix<double>&, const bool, const bool);
+ template void apply_boundary_values (
+ const std::set<unsigned int>&,
+ BlockSparseMatrix<float>&, const bool);
+ template void apply_boundary_values (
+ const std::set<unsigned int>&,
+ BlockSparseMatrix<double>&, const bool);
+}
DEAL_II_NAMESPACE_CLOSE
// $Id$
// Version: $Name$
//
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by the deal.II authors
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
for (PATTERN : SPARSITY_PATTERNS; deal_II_dimension : DIMENSIONS)
{
-template void
-MGTools::make_sparsity_pattern<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension> &,
- PATTERN &,
- const unsigned int);
-
-template void
-MGTools::make_flux_sparsity_pattern<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension> &,
- PATTERN &,
- const unsigned int);
-
-template void
-MGTools::make_flux_sparsity_pattern_edge<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension> &,
- PATTERN &,
- const unsigned int);
+ namespace MGTools
+ \{
+
+ template void
+ make_sparsity_pattern<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension> &,
+ PATTERN &,
+ const unsigned int);
+
+ template void
+ make_flux_sparsity_pattern<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension> &,
+ PATTERN &,
+ const unsigned int);
+
+ template void
+ make_flux_sparsity_pattern_edge<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension> &,
+ PATTERN &,
+ const unsigned int);
#if deal_II_dimension > 1
-template void
-MGTools::make_flux_sparsity_pattern<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension> &,
- PATTERN &,
- const unsigned int,
- const Table<2,DoFTools::Coupling>&,
- const Table<2,DoFTools::Coupling>&);
-
-template void
-MGTools::make_flux_sparsity_pattern_edge<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension> &,
- PATTERN &,
- const unsigned int,
- const Table<2,DoFTools::Coupling>&);
-
+ template void
+ make_flux_sparsity_pattern<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension> &,
+ PATTERN &,
+ const unsigned int,
+ const Table<2,DoFTools::Coupling>&,
+ const Table<2,DoFTools::Coupling>&);
+
+ template void
+ make_flux_sparsity_pattern_edge<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension> &,
+ PATTERN &,
+ const unsigned int,
+ const Table<2,DoFTools::Coupling>&);
#endif
+ \}
}
for (deal_II_dimension : DIMENSIONS)
{
-#if deal_II_dimension > 1
-template void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<deal_II_dimension>&, unsigned int,
- std::vector<unsigned int>&, const DoFTools::Coupling);
-template void
-MGTools::compute_row_length_vector(
- const MGDoFHandler<deal_II_dimension>&, unsigned int,
- std::vector<unsigned int>&,
- const Table<2,DoFTools::Coupling>&, const Table<2,DoFTools::Coupling>&);
-#endif
-
-template void MGTools::count_dofs_per_component<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
- bool, std::vector<unsigned int>);
-template void MGTools::count_dofs_per_component<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
- std::vector<unsigned int>);
-template void MGTools::count_dofs_per_block<deal_II_dimension> (
- const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
- std::vector<unsigned int>);
+ namespace MGTools
+ \{
#if deal_II_dimension > 1
-template void MGTools::make_boundary_list(
- const MGDoFHandler<deal_II_dimension>&,
- const FunctionMap<deal_II_dimension>::type&,
- std::vector<std::set<unsigned int> >&,
- const std::vector<bool>&);
+ template void
+ compute_row_length_vector(
+ const MGDoFHandler<deal_II_dimension>&, unsigned int,
+ std::vector<unsigned int>&, const DoFTools::Coupling);
+ template void
+ compute_row_length_vector(
+ const MGDoFHandler<deal_II_dimension>&, unsigned int,
+ std::vector<unsigned int>&,
+ const Table<2,DoFTools::Coupling>&, const Table<2,DoFTools::Coupling>&);
#endif
-template void MGTools::make_boundary_list(
- const MGDoFHandler<deal_II_dimension>&,
- const FunctionMap<deal_II_dimension>::type&,
- std::vector<IndexSet>&,
- const std::vector<bool>&);
+ template void count_dofs_per_component<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
+ bool, std::vector<unsigned int>);
+ template void count_dofs_per_component<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
+ std::vector<unsigned int>);
+ template void count_dofs_per_block<deal_II_dimension> (
+ const MGDoFHandler<deal_II_dimension>&, std::vector<std::vector<unsigned int> >&,
+ std::vector<unsigned int>);
#if deal_II_dimension > 1
-template
-void
-MGTools::
-extract_inner_interface_dofs (const MGDoFHandler<deal_II_dimension> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs,
- std::vector<std::vector<bool> > &boundary_interface_dofs);
-template
-void
-MGTools::
-extract_inner_interface_dofs (const MGDoFHandler<deal_II_dimension> &mg_dof_handler,
- std::vector<std::vector<bool> > &interface_dofs);
+ template void make_boundary_list(
+ const MGDoFHandler<deal_II_dimension>&,
+ const FunctionMap<deal_II_dimension>::type&,
+ std::vector<std::set<unsigned int> >&,
+ const std::vector<bool>&);
#endif
-#if deal_II_dimension < 3
-
-template void MGTools::count_dofs_per_block<deal_II_dimension,deal_II_dimension+1> (
- const MGDoFHandler<deal_II_dimension,deal_II_dimension+1>&,
- std::vector<std::vector<unsigned int> >&, std::vector<unsigned int>);
+ template void make_boundary_list(
+ const MGDoFHandler<deal_II_dimension>&,
+ const FunctionMap<deal_II_dimension>::type&,
+ std::vector<IndexSet>&,
+ const std::vector<bool>&);
+
+ template
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<deal_II_dimension> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs,
+ std::vector<std::vector<bool> > &boundary_interface_dofs);
+ template
+ void
+ extract_inner_interface_dofs (const MGDoFHandler<deal_II_dimension> &mg_dof_handler,
+ std::vector<std::vector<bool> > &interface_dofs);
+#if deal_II_dimension < 3
+ template void count_dofs_per_block<deal_II_dimension,deal_II_dimension+1> (
+ const MGDoFHandler<deal_II_dimension,deal_II_dimension+1>&,
+ std::vector<std::vector<unsigned int> >&, std::vector<unsigned int>);
#endif
+ \}
}
= mg_component_start[level][mg_target_component[component]];
const unsigned int global_start
= component_start[target_component[component]];
- temp_copy_indices[level_dof_indices[i]-level_start] =
+ temp_copy_indices[level_dof_indices[i]-level_start] =
global_dof_indices[i] - global_start;
}
}
// $Id$
// Version: $Name$
//
-// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by the deal.II authors
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011 by the deal.II authors
//
// This file is subject to QPL and may not be distributed
// without copyright and license information. Please refer
DEAL_II_NAMESPACE_OPEN
-void
-VectorTools::subtract_mean_value(Vector<double> &v,
- const std::vector<bool> &p_select)
+namespace VectorTools
{
- const unsigned int n = v.size();
- Assert(n == p_select.size(),
- ExcDimensionMismatch(n, p_select.size()));
-
- double s = 0;
- unsigned int counter = 0;
-
- for (unsigned int i=0; i<n; ++i)
- if (p_select[i])
- {
- s += v(i);
- ++counter;
- }
- Assert (counter > 0, ExcNoComponentSelected());
-
- s /= counter;
-
- for (unsigned int i=0; i<n; ++i)
- if (p_select[i])
- v(i) -= s;
-}
+ void
+ subtract_mean_value(Vector<double> &v,
+ const std::vector<bool> &p_select)
+ {
+ const unsigned int n = v.size();
+ Assert(n == p_select.size(),
+ ExcDimensionMismatch(n, p_select.size()));
+
+ double s = 0;
+ unsigned int counter = 0;
+
+ for (unsigned int i=0; i<n; ++i)
+ if (p_select[i])
+ {
+ s += v(i);
+ ++counter;
+ }
+ Assert (counter > 0, ExcNoComponentSelected());
+
+ s /= counter;
+
+ for (unsigned int i=0; i<n; ++i)
+ if (p_select[i])
+ v(i) -= s;
+ }
+}
// ---------------------------- explicit instantiations --------------------
//
//---------------------------------------------------------------------------
+
for (VEC : SERIAL_VECTORS ; deal_II_dimension : DIMENSIONS)
-{
+{
+ namespace VectorTools \{
+
template
- void VectorTools::interpolate
+ void interpolate
(const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
- template
- void VectorTools::interpolate
+ template
+ void interpolate
(const DoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
- template
- void VectorTools::interpolate
+ template
+ void interpolate
(const Mapping<deal_II_dimension>&,
const hp::DoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
template
- void VectorTools::interpolate
+ void interpolate
(const hp::DoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
template
- void VectorTools::interpolate
+ void interpolate
(const Mapping<deal_II_dimension>&,
const MGDoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
template
- void VectorTools::interpolate
+ void interpolate
(const MGDoFHandler<deal_II_dimension>&,
const Function<deal_II_dimension>&,
VEC&);
template
- void VectorTools::interpolate
+ void interpolate
(const DoFHandler<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const FullMatrix<double>&,
VEC&);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>&,
#if deal_II_dimension != 3
template
- void VectorTools::integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_dimension+1>
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_dimension+1>
(const DoFHandler<deal_II_dimension, deal_II_dimension+1>&,
const VEC&,
const Function<deal_II_dimension+1>&,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_dimension+1 >
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_dimension+1 >
(const DoFHandler<deal_II_dimension, deal_II_dimension+1>&,
const VEC&,
const Function<deal_II_dimension+1>&,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_dimension+1>
- (const Mapping<deal_II_dimension, deal_II_dimension+1>&,
+ void integrate_difference<deal_II_dimension, VEC, Vector<float>, deal_II_dimension+1>
+ (const Mapping<deal_II_dimension, deal_II_dimension+1>&,
const DoFHandler<deal_II_dimension, deal_II_dimension+1>&,
const VEC&,
const Function<deal_II_dimension+1>&,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_dimension+1 >
- (const Mapping<deal_II_dimension, deal_II_dimension+1>&,
+ void integrate_difference<deal_II_dimension, VEC, Vector<double>, deal_II_dimension+1 >
+ (const Mapping<deal_II_dimension, deal_II_dimension+1>&,
const DoFHandler<deal_II_dimension, deal_II_dimension+1>&,
const VEC&,
const Function<deal_II_dimension+1>&,
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>&,
const Function<deal_II_dimension>*,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>*,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const VEC&,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>&,
const Function<deal_II_dimension>*,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>&,
const Function<deal_II_dimension>*,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const hp::MappingCollection<deal_II_dimension>&,
const hp::DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>*,
const double);
template
- void VectorTools::integrate_difference<deal_II_dimension>
+ void integrate_difference<deal_II_dimension>
(const hp::MappingCollection<deal_II_dimension>&,
const hp::DoFHandler<deal_II_dimension>&,
const VEC&,
const double);
template
- void VectorTools::point_difference<deal_II_dimension> (
+ void point_difference<deal_II_dimension> (
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Function<deal_II_dimension>&,
const Point<deal_II_dimension>&);
template
- void VectorTools::point_difference<deal_II_dimension> (
+ void point_difference<deal_II_dimension> (
const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Point<deal_II_dimension>&);
template
- void VectorTools::point_value<deal_II_dimension> (
+ void point_value<deal_II_dimension> (
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Point<deal_II_dimension>&,
Vector<double>&);
template
- double VectorTools::point_value<deal_II_dimension> (
+ double point_value<deal_II_dimension> (
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Point<deal_II_dimension>&);
template
- void VectorTools::point_value<deal_II_dimension> (
+ void point_value<deal_II_dimension> (
const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const VEC&,
Vector<double>&);
template
- double VectorTools::point_value<deal_II_dimension> (
+ double point_value<deal_II_dimension> (
const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const VEC&,
const Point<deal_II_dimension>&);
template
- double VectorTools::compute_mean_value<deal_II_dimension>
+ double compute_mean_value<deal_II_dimension>
(const Mapping<deal_II_dimension>&,
const DoFHandler<deal_II_dimension>&,
const Quadrature<deal_II_dimension>&,
const VEC&,
const unsigned int);
template
- double VectorTools::compute_mean_value<deal_II_dimension>
+ double compute_mean_value<deal_II_dimension>
(const DoFHandler<deal_II_dimension>&,
const Quadrature<deal_II_dimension>&,
const VEC&,
#if deal_II_dimension < 3
template
- double VectorTools::compute_mean_value<deal_II_dimension>
+ double compute_mean_value<deal_II_dimension>
(const Mapping<deal_II_dimension,deal_II_dimension+1>&,
const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
const Quadrature<deal_II_dimension>&,
const VEC&,
const unsigned int);
template
- double VectorTools::compute_mean_value<deal_II_dimension>
+ double compute_mean_value<deal_II_dimension>
(const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
const Quadrature<deal_II_dimension>&,
const VEC&,
#endif
template
- void VectorTools::project
+ void project
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const ConstraintMatrix &,
const bool);
template
- void VectorTools::project
+ void project
(const DoFHandler<deal_II_dimension> &,
const ConstraintMatrix &,
const Quadrature<deal_II_dimension> &,
#if deal_II_dimension != 3
template
- void VectorTools::interpolate
+ void interpolate
(const Mapping<deal_II_dimension,deal_II_dimension+1>&,
const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
const Function<deal_II_dimension+1>&,
VEC&);
template
- void VectorTools::interpolate
+ void interpolate
(const DoFHandler<deal_II_dimension,deal_II_dimension+1>&,
const Function<deal_II_dimension+1>&,
VEC&);
template
- void VectorTools::project
+ void project
(const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const ConstraintMatrix &,
const bool);
template
- void VectorTools::project
+ void project
(const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const ConstraintMatrix &,
const Quadrature<deal_II_dimension> &,
const Quadrature<deal_II_dimension-1> &,
const bool);
#endif
-
+ \}
}
for ( deal_II_dimension : DIMENSIONS )
{
+namespace VectorTools \{
template
-void VectorTools::create_right_hand_side<deal_II_dimension>
+void create_right_hand_side<deal_II_dimension>
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const Quadrature<deal_II_dimension> &,
const Function<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_right_hand_side<deal_II_dimension>
+void create_right_hand_side<deal_II_dimension>
(const DoFHandler<deal_II_dimension> &,
const Quadrature<deal_II_dimension> &,
const Function<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_right_hand_side<deal_II_dimension>
+void create_right_hand_side<deal_II_dimension>
(const hp::MappingCollection<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const hp::QCollection<deal_II_dimension> &,
const Function<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_right_hand_side<deal_II_dimension>
+void create_right_hand_side<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension> &,
const hp::QCollection<deal_II_dimension> &,
const Function<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_point_source_vector<deal_II_dimension>
+void create_point_source_vector<deal_II_dimension>
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const Point<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_point_source_vector<deal_II_dimension>
+void create_point_source_vector<deal_II_dimension>
(const DoFHandler<deal_II_dimension> &,
const Point<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_point_source_vector<deal_II_dimension>
+void create_point_source_vector<deal_II_dimension>
(const hp::MappingCollection<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const Point<deal_II_dimension> &,
Vector<double> &);
template
-void VectorTools::create_point_source_vector<deal_II_dimension>
+void create_point_source_vector<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension> &,
const Point<deal_II_dimension> &,
Vector<double> &);
#if deal_II_dimension > 1
template
void
-VectorTools::create_boundary_right_hand_side<deal_II_dimension>
+create_boundary_right_hand_side<deal_II_dimension>
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const Quadrature<deal_II_dimension-1> &,
template
void
-VectorTools::create_boundary_right_hand_side<deal_II_dimension>
+create_boundary_right_hand_side<deal_II_dimension>
(const DoFHandler<deal_II_dimension> &,
const Quadrature<deal_II_dimension-1> &,
const Function<deal_II_dimension> &,
#if deal_II_dimension > 1
template
void
-VectorTools::create_boundary_right_hand_side<deal_II_dimension>
+create_boundary_right_hand_side<deal_II_dimension>
(const hp::MappingCollection<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const hp::QCollection<deal_II_dimension-1> &,
template
void
-VectorTools::create_boundary_right_hand_side<deal_II_dimension>
+create_boundary_right_hand_side<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension> &,
const hp::QCollection<deal_II_dimension-1> &,
const Function<deal_II_dimension> &,
const std::set<unsigned char> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension> &,
const unsigned char,
const Function<deal_II_dimension> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension> &,
const MGDoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
ConstraintMatrix &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
ConstraintMatrix &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
ConstraintMatrix &,
#if deal_II_dimension < 3
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
const Function<deal_II_dimension+1> &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
ConstraintMatrix &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
ConstraintMatrix &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values (
+void interpolate_boundary_values (
const MGDoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
ConstraintMatrix &,
#if deal_II_dimension > 1
template
-void VectorTools::project_boundary_values<deal_II_dimension>
+void project_boundary_values<deal_II_dimension>
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
#endif
template
-void VectorTools::project_boundary_values<deal_II_dimension>
+void project_boundary_values<deal_II_dimension>
(const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const Quadrature<deal_II_dimension-1>&,
template
-void VectorTools::project_boundary_values<deal_II_dimension>
+void project_boundary_values<deal_II_dimension>
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
ConstraintMatrix&, std::vector<unsigned int>);
template
-void VectorTools::project_boundary_values<deal_II_dimension>
+void project_boundary_values<deal_II_dimension>
(const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const Quadrature<deal_II_dimension-1>&,
#if deal_II_dimension != 1
template
-void VectorTools::project_boundary_values_curl_conforming<deal_II_dimension>
+void project_boundary_values_curl_conforming<deal_II_dimension>
(const DoFHandler<deal_II_dimension>&,
const unsigned int,
const Function<deal_II_dimension>&,
ConstraintMatrix&,
const Mapping<deal_II_dimension>&);
template
-void VectorTools::project_boundary_values_curl_conforming<deal_II_dimension>
+void project_boundary_values_curl_conforming<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension>&,
const unsigned int,
const Function<deal_II_dimension>&,
ConstraintMatrix&,
const hp::MappingCollection<deal_II_dimension>&);
template
-void VectorTools::project_boundary_values_div_conforming<deal_II_dimension>
+void project_boundary_values_div_conforming<deal_II_dimension>
(const DoFHandler<deal_II_dimension>&,
const unsigned int,
const Function<deal_II_dimension>&,
ConstraintMatrix&,
const Mapping<deal_II_dimension>&);
template
-void VectorTools::project_boundary_values_div_conforming<deal_II_dimension>
+void project_boundary_values_div_conforming<deal_II_dimension>
(const hp::DoFHandler<deal_II_dimension>&,
const unsigned int,
const Function<deal_II_dimension>&,
const hp::MappingCollection<deal_II_dimension>&);
template
void
-VectorTools::compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
+compute_no_normal_flux_constraints (const DoFHandler<deal_II_dimension> &dof_handler,
const unsigned int first_vector_component,
const std::set<unsigned char> &boundary_ids,
ConstraintMatrix &constraints,
const Mapping<deal_II_dimension> &mapping);
template
void
-VectorTools::compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
+compute_no_normal_flux_constraints (const hp::DoFHandler<deal_II_dimension> &dof_handler,
const unsigned int first_vector_component,
const std::set<unsigned char> &boundary_ids,
ConstraintMatrix &constraints,
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension> &,
const MGDoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension> &,
const DoFHandler<deal_II_dimension> &,
const unsigned char,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension> &,
const hp::DoFHandler<deal_II_dimension> &,
const unsigned char,
#if deal_II_dimension < 3
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const FunctionMap<deal_II_dimension+1>::type &,
const std::vector<bool> &);
template
-void VectorTools::interpolate_boundary_values
+void interpolate_boundary_values
(const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const unsigned char,
template
void
-VectorTools::interpolate_boundary_values
+interpolate_boundary_values
(const DoFHandler<deal_II_dimension> &,
const FunctionMap<deal_II_dimension>::type &,
std::map<unsigned int,double> &,
#if deal_II_dimension != 3
template
-void VectorTools::create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
+void create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
(const Mapping<deal_II_dimension,deal_II_dimension+1> &,
const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const Quadrature<deal_II_dimension> &,
const Function<deal_II_dimension+1> &,
Vector<double> &);
template
-void VectorTools::create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
+void create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
(const DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
const Quadrature<deal_II_dimension> &,
const Function<deal_II_dimension+1> &,
Vector<double> &);
// template
-// void VectorTools::create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
+// void create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
// (const hp::MappingCollection<deal_II_dimension,deal_II_dimension+1> &,
// const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
// const hp::QCollection<deal_II_dimension> &,
// const Function<deal_II_dimension+1> &,
// Vector<double> &);
// template
-// void VectorTools::create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
+// void create_right_hand_side<deal_II_dimension,deal_II_dimension+1>
// (const hp::DoFHandler<deal_II_dimension,deal_II_dimension+1> &,
// const hp::QCollection<deal_II_dimension> &,
// const Function<deal_II_dimension+1> &,
// Vector<double> &);
#endif
+ \}
}
+