* constrained to, inhomogeneities) is
* kept and nothing happens.
*
- * Please note that when combining
- * adaptively refined meshes with hanging
- * node constraints and inhomogeneous
- * Dirichlet boundary conditions within
+ * @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 Dirichlet
- * boundary conditions should be
- * interpolated. This makes sure that the
- * discretization remains H<sup>1</sup>
- * conforming as is needed e.g. for the
- * Laplace equation in 3D, as hanging
- * nodes on the boundary should be still
- * set to the weighted average of
- * neighbors, and not the actual
- * Dirichlet value.
- * *
+ * 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
* inhomogeneities) is kept and nothing
* happens.
*
- * Please note that when combining
- * adaptively refined meshes with hanging
- * node constraints and inhomogeneous
- * Dirichlet boundary conditions within
+ * @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 Dirichlet
- * boundary conditions should be
- * interpolated. This makes sure that the
- * discretization remains H<sup>1</sup>
- * conforming as is needed e.g. for the
- * Laplace equation in 3D, as hanging
- * nodes on the boundary should be still
- * set to the weighted average of
- * neighbors, and not the actual
- * Dirichlet value.
+ * 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
* first, and then completed by hanging
* node constraints, in order to make sure
* that the discretization remains
- * consistent.
+ * 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
* compute the normal vector $\vec n$ at
* the boundary points.
*
+ * @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>
*
* indices, and $\vec n$ by the
* vector specified as the second
* argument.
+ *
+ * The function does not add constraints
+ * if a degree of freedom is already
+ * constrained in the constraints object.
*/
template <int dim>
void
const Tensor<1,dim> &constraining_vector,
ConstraintMatrix &constraints)
{
+
// choose the DoF that has the
// largest component in the
// constraining_vector as the
{
if (std::fabs(constraining_vector[0]) > std::fabs(constraining_vector[1]))
{
- constraints.add_line (dof_indices.dof_indices[0]);
+ if (!constraints.is_constrained(dof_indices.dof_indices[0]))
+ {
+ constraints.add_line (dof_indices.dof_indices[0]);
- if (std::fabs (constraining_vector[1]/constraining_vector[0])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[0],
- dof_indices.dof_indices[1],
- -constraining_vector[1]/constraining_vector[0]);
+ if (std::fabs (constraining_vector[1]/constraining_vector[0])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[0],
+ dof_indices.dof_indices[1],
+ -constraining_vector[1]/constraining_vector[0]);
+ }
}
else
{
- constraints.add_line (dof_indices.dof_indices[1]);
+ if (!constraints.is_constrained(dof_indices.dof_indices[1]))
+ {
+ constraints.add_line (dof_indices.dof_indices[1]);
- if (std::fabs (constraining_vector[0]/constraining_vector[1])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[1],
- dof_indices.dof_indices[0],
- -constraining_vector[0]/constraining_vector[1]);
+ if (std::fabs (constraining_vector[0]/constraining_vector[1])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[1],
+ dof_indices.dof_indices[0],
+ -constraining_vector[0]/constraining_vector[1]);
+ }
}
break;
}
&&
(std::fabs(constraining_vector[0]) >= std::fabs(constraining_vector[2])))
{
- constraints.add_line (dof_indices.dof_indices[0]);
-
- if (std::fabs (constraining_vector[1]/constraining_vector[0])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[0],
- dof_indices.dof_indices[1],
- -constraining_vector[1]/constraining_vector[0]);
-
- if (std::fabs (constraining_vector[2]/constraining_vector[0])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[0],
- dof_indices.dof_indices[2],
- -constraining_vector[2]/constraining_vector[0]);
+ if (!constraints.is_constrained(dof_indices.dof_indices[0]))
+ {
+ constraints.add_line (dof_indices.dof_indices[0]);
+
+ if (std::fabs (constraining_vector[1]/constraining_vector[0])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[0],
+ dof_indices.dof_indices[1],
+ -constraining_vector[1]/constraining_vector[0]);
+
+ if (std::fabs (constraining_vector[2]/constraining_vector[0])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[0],
+ dof_indices.dof_indices[2],
+ -constraining_vector[2]/constraining_vector[0]);
+ }
}
else
if ((std::fabs(constraining_vector[1]) >= std::fabs(constraining_vector[0]))
&&
(std::fabs(constraining_vector[1]) >= std::fabs(constraining_vector[2])))
{
- constraints.add_line (dof_indices.dof_indices[1]);
-
- if (std::fabs (constraining_vector[0]/constraining_vector[1])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[1],
- dof_indices.dof_indices[0],
- -constraining_vector[0]/constraining_vector[1]);
-
- if (std::fabs (constraining_vector[2]/constraining_vector[1])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[1],
- dof_indices.dof_indices[2],
- -constraining_vector[2]/constraining_vector[1]);
+ if (!constraints.is_constrained(dof_indices.dof_indices[1]))
+ {
+ constraints.add_line (dof_indices.dof_indices[1]);
+
+ if (std::fabs (constraining_vector[0]/constraining_vector[1])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[1],
+ dof_indices.dof_indices[0],
+ -constraining_vector[0]/constraining_vector[1]);
+
+ if (std::fabs (constraining_vector[2]/constraining_vector[1])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[1],
+ dof_indices.dof_indices[2],
+ -constraining_vector[2]/constraining_vector[1]);
+ }
}
else
{
- constraints.add_line (dof_indices.dof_indices[2]);
-
- if (std::fabs (constraining_vector[0]/constraining_vector[2])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[2],
- dof_indices.dof_indices[0],
- -constraining_vector[0]/constraining_vector[2]);
-
- if (std::fabs (constraining_vector[1]/constraining_vector[2])
- > std::numeric_limits<double>::epsilon())
- constraints.add_entry (dof_indices.dof_indices[2],
- dof_indices.dof_indices[1],
- -constraining_vector[1]/constraining_vector[2]);
+ if (!constraints.is_constrained(dof_indices.dof_indices[2]))
+ {
+ constraints.add_line (dof_indices.dof_indices[2]);
+
+ if (std::fabs (constraining_vector[0]/constraining_vector[2])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[2],
+ dof_indices.dof_indices[0],
+ -constraining_vector[0]/constraining_vector[2]);
+
+ if (std::fabs (constraining_vector[1]/constraining_vector[2])
+ > std::numeric_limits<double>::epsilon())
+ constraints.add_entry (dof_indices.dof_indices[2],
+ dof_indices.dof_indices[1],
+ -constraining_vector[1]/constraining_vector[2]);
+ }
}
break;
// constrained. enter
// this into the
// constraint matrix
+ //
+ // ignore dofs already
+ // constrained
for (unsigned int i=0; i<dim; ++i)
- {
- constraints.add_line (same_dof_range[0]->first.dof_indices[i]);
- // no add_entries here
- }
+ if (!constraints.is_constrained (same_dof_range[0]
+ ->first.dof_indices[i]))
+ {
+ constraints.add_line (same_dof_range[0]->first.dof_indices[i]);
+ // no add_entries here
+ }
break;
}