Skip to content

Commit

Permalink
fix normal on a coarse mesh
Browse files Browse the repository at this point in the history
  • Loading branch information
zjiaqi2018 committed Sep 19, 2022
1 parent 4b79152 commit 03e99f0
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 3 deletions.
42 changes: 39 additions & 3 deletions source/grid/manifold.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,45 @@ Manifold<3, 3>::normal_vector(const Triangulation<3, 3>::face_iterator &face,
ExcMessage("The search for possible directions did not succeed."));

// Compute tangents and normal for selected vertices
Tensor<1, spacedim> t1 = get_tangent_vector(p, vertices[first_index]);
Tensor<1, spacedim> t2 = get_tangent_vector(p, vertices[second_index]);
Tensor<1, spacedim> normal = cross_product_3d(t1, t2);
Tensor<1, spacedim> t1;
Tensor<1, spacedim> t2;
Tensor<1, spacedim> normal;

bool done = false;
std::vector<bool> tested_vertices(vertices.size(), false);
tested_vertices[first_index] = true;
tested_vertices[second_index] = true;

do
{
// Compute tangents and normal for selected vertices
t1 = get_tangent_vector(p, vertices[first_index]);
t2 = get_tangent_vector(p, vertices[second_index]);
normal = cross_product_3d(t1, t2);

// if normal is zero, try some other combination of veritices
if (normal.norm_square() < 1e4 * std::numeric_limits<double>::epsilon() *
t1.norm_square() * t2.norm_square())
{
// See if we have tested already all vertices
auto first_false =
std::find(tested_vertices.begin(), tested_vertices.end(), false);
if (first_false == tested_vertices.end())
{
done = true;
}
else
{
*first_false = true;
second_index = first_false - tested_vertices.begin();
}
}
else
{
done = true;
}
}
while (!done);

Assert(
normal.norm_square() > 1e4 * std::numeric_limits<double>::epsilon() *
Expand Down
103 changes: 103 additions & 0 deletions tests/manifold/spherical_manifold_14.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// ---------------------------------------------------------------------
//
// Copyright (C) 2012 - 2022 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE.md at
// the top level directory of deal.II.
//
// ---------------------------------------------------------------------



// A test for Issue #14183. On a very coarse mesh, the
// vertices chosen to compute the normal vector may
// lead to two parallel tangent vectors, resulting
// in a zero normal vector. This can be fixed by
// choosing other combinations of vertices when the
// normal vector is too close to a zero vector.

#include <deal.II/base/exceptions.h>
#include <deal.II/base/function.h>

#include <deal.II/dofs/dof_handler.h>

#include <deal.II/fe/fe_q.h>
#include <deal.II/fe/fe_system.h>
#include <deal.II/fe/mapping_q.h>

#include <deal.II/grid/grid_generator.h>
#include <deal.II/grid/grid_out.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/grid/tria.h>

#include <deal.II/numerics/data_out.h>
#include <deal.II/numerics/vector_tools.h>
#include <deal.II/numerics/vector_tools_constraints.h>

#include "../tests.h"

int
main()
{
initlog();
deallog.get_file_stream().precision(7);
deallog.get_file_stream().setf(std::ios::fixed);

{
const unsigned int dim = 3;
Triangulation<dim> triangulation(
Triangulation<dim>::limit_level_difference_at_vertices);
GridGenerator::half_hyper_shell(triangulation, Point<dim>(), 0.5, 1.);

std::set<types::boundary_id> no_flux_boundary{0};
MappingQ<dim> mapping(2);

FESystem<dim> fe(FE_Q<dim>(2), dim);
DoFHandler<dim> dofh(triangulation);

dofh.distribute_dofs(fe);

AffineConstraints<double> constraints;


const unsigned int face_no = 0;
const std::vector<Point<dim - 1>> &unit_support_points =
fe.get_unit_face_support_points(face_no);

Assert(unit_support_points.size() == fe.n_dofs_per_face(),
ExcInternalError());


Quadrature<dim - 1> face_quadrature(unit_support_points);

FEFaceValues<dim> fe_face_values(mapping,
fe,
face_quadrature,
update_quadrature_points |
update_normal_vectors);


std::set<types::boundary_id>::iterator b_id;

for (const auto &cell : dofh.active_cell_iterators())
if (!cell->is_artificial())
for (const unsigned int face_no : cell->face_indices())
if ((b_id = no_flux_boundary.find(
cell->face(face_no)->boundary_id())) != no_flux_boundary.end())
{
fe_face_values.reinit(cell, face_no);
for (unsigned int i = 0; i < face_quadrature.size(); ++i)
Tensor<1, dim> normal_vector =
(cell->face(face_no)->get_manifold().normal_vector(
cell->face(face_no), fe_face_values.quadrature_point(i)));
}

deallog << " OK! " << std::endl;
}
}
2 changes: 2 additions & 0 deletions tests/manifold/spherical_manifold_14.output
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

DEAL:: OK!

0 comments on commit 03e99f0

Please sign in to comment.