16 #include <deal.II/base/tensor.h> 17 #include <deal.II/base/table.h> 18 #include <deal.II/base/std_cxx14/memory.h> 19 #include <deal.II/grid/manifold.h> 20 #include <deal.II/grid/tria.h> 21 #include <deal.II/grid/tria_iterator.h> 22 #include <deal.II/grid/tria_accessor.h> 23 #include <deal.II/fe/fe_q.h> 27 #include <boost/container/small_vector.hpp> 29 DEAL_II_NAMESPACE_OPEN
34 template <
int dim,
int spacedim>
46 template <
int dim,
int spacedim>
53 const std::array<Point<spacedim>, 2> vertices {{p1, p2}};
54 return project_to_manifold(make_array_view(vertices.begin(), vertices.end()),
60 template <
int dim,
int spacedim>
66 const double tol = 1e-10;
67 const unsigned int n_points = surrounding_points.size();
70 ExcMessage(
"There should be at least one point."));
73 ExcMessage(
"There should be as many surrounding points as weights given."));
75 Assert(std::abs(std::accumulate(weights.
begin(), weights.
end(), 0.0)-1.0) < tol,
76 ExcMessage(
"The weights for the individual points should sum to 1!"));
81 boost::container::small_vector<unsigned int, 100> permutation(n_points);
82 std::iota(permutation.begin(), permutation.end(), 0u);
83 std::sort(permutation.begin(), permutation.end(),
84 [&weights](
const std::size_t a,
const std::size_t b)
86 return weights[a] < weights[b];
91 double w = weights[permutation[0]];
93 for (
unsigned int i=1; i<n_points; ++i)
96 if ( (weights[permutation[i]] + w) < tol )
99 weight = w/(weights[permutation[i]] + w);
101 if (std::abs(weight) > 1e-14)
102 p = get_intermediate_point(p, surrounding_points[permutation[i]],1.0 - weight );
103 w += weights[permutation[i]];
111 template <
int dim,
int spacedim>
120 for (
unsigned int row=0; row<weights.
size(0); ++row)
122 new_points[row] = get_new_point(make_array_view(surrounding_points.begin(),
123 surrounding_points.end()),
124 make_array_view(weights,
137 const int spacedim=2;
142 = ((p-face->vertex(0)).norm_square() > (p-face->vertex(1)).norm_square() ?
143 -get_tangent_vector(p, face->vertex(0)) :
144 get_tangent_vector(p, face->vertex(1)));
148 return normal/normal.
norm();
159 const int spacedim=3;
161 const std::array<Point<spacedim>, 4> vertices
162 {{face->vertex(0), face->vertex(1), face->vertex(2), face->vertex(3)}};
163 const std::array<double, 4> distances
165 const double max_distance = std::max(std::max(distances[0], distances[1]),
166 std::max(distances[2], distances[3]));
174 double abs_cos_angle = std::numeric_limits<double>::max();
177 for (
unsigned int i=0; i<3; ++i)
178 if (distances[i] > 1e-8*max_distance)
179 for (
unsigned int j=i+1; j<4; ++j)
180 if (distances[j] > 1e-8*max_distance)
182 const double new_angle = (p-vertices[i]) * (p-vertices[j]) /
183 (distances[i]*distances[j]);
186 if (std::abs(new_angle) < 0.999 * abs_cos_angle)
188 abs_cos_angle = std::abs(new_angle);
194 ExcMessage(
"The search for possible directions did not succeed."));
203 ExcMessage(
"Manifold::normal_vector was unable to find a suitable combination " 204 "of vertices to compute a normal on this face. We chose the secants " 205 "that are as orthogonal as possible, but tangents appear to be " 206 "linearly dependent. Check for distorted faces in your triangulation."));
215 if (reference_normal * normal < 0.0)
218 return normal / normal.
norm();
223 template <
int dim,
int spacedim>
239 FaceVertexNormals &n)
const 241 n[0] = cross_product_2d(get_tangent_vector(face->vertex(0), face->vertex(1)));
242 n[1] = -cross_product_2d(get_tangent_vector(face->vertex(1), face->vertex(0)));
244 for (
unsigned int i=0; i<2; ++i)
247 "computed normals have " 259 FaceVertexNormals &n)
const 261 n[0] = cross_product_3d
262 (get_tangent_vector(face->vertex(0), face->vertex(1)),
263 get_tangent_vector(face->vertex(0), face->vertex(2)));
265 n[1] = cross_product_3d
266 (get_tangent_vector(face->vertex(1), face->vertex(3)),
267 get_tangent_vector(face->vertex(1), face->vertex(0)));
269 n[2] = cross_product_3d
270 (get_tangent_vector(face->vertex(2), face->vertex(0)),
271 get_tangent_vector(face->vertex(2), face->vertex(3)));
273 n[3] = cross_product_3d
274 (get_tangent_vector(face->vertex(3), face->vertex(2)),
275 get_tangent_vector(face->vertex(3), face->vertex(1)));
277 for (
unsigned int i=0; i<4; ++i)
280 "computed normals have " 288 template <
int dim,
int spacedim>
292 FaceVertexNormals &n)
const 294 for (
unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
296 n[v] = normal_vector(face, face->vertex(v));
303 template <
int dim,
int spacedim>
309 return get_new_point (make_array_view(points_weights.first.begin(),
310 points_weights.first.end()),
311 make_array_view(points_weights.second.begin(),
312 points_weights.second.end()));
317 template <
int dim,
int spacedim>
323 return get_new_point (make_array_view(points_weights.first.begin(),
324 points_weights.first.end()),
325 make_array_view(points_weights.second.begin(),
326 points_weights.second.end()));
331 template <
int dim,
int spacedim>
341 return get_new_point_on_line (face);
343 return get_new_point_on_quad (face);
351 template <
int dim,
int spacedim>
359 return get_new_point_on_line (cell);
361 return get_new_point_on_quad (cell);
363 return get_new_point_on_hex (cell);
437 template <
int dim,
int spacedim>
454 return get_new_point (make_array_view(points_weights.first.begin(),
455 points_weights.first.end()),
456 make_array_view(points_weights.second.begin(),
457 points_weights.second.end()));
462 template <
int dim,
int spacedim>
467 const double epsilon = 1e-8;
469 const std::array<Point<spacedim>, 2> points {{x1, x2}};
470 const std::array<double, 2> weights {{epsilon, 1.0 - epsilon}};
471 const Point<spacedim> neighbor_point = get_new_point (make_array_view(points.begin(),
473 make_array_view(weights.begin(),
475 return (neighbor_point-x1)/epsilon;
485 normalized_alternating_product (
const Tensor<1,3> ( &)[1])
497 normalized_alternating_product (
const Tensor<1,3> (&basis_vectors)[2])
499 Tensor<1,3> tmp = cross_product_3d (basis_vectors[0], basis_vectors[1]);
500 return tmp/tmp.
norm();
506 template <
int dim,
int spacedim>
508 const double tolerance)
510 periodicity(periodicity),
516 template<
int dim,
int spacedim>
517 std::unique_ptr<Manifold<dim, spacedim> >
520 return std_cxx14::make_unique<FlatManifold<dim,spacedim> >(periodicity, tolerance);
525 template <
int dim,
int spacedim>
531 Assert(std::abs(std::accumulate(weights.
begin(), weights.
end(), 0.0)-1.0) < 1e-10,
532 ExcMessage(
"The weights for the individual points should sum to 1!"));
539 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
540 p += surrounding_points[i] * weights[i];
546 for (
unsigned int d=0; d<spacedim; ++d)
547 if (periodicity[d] > 0)
548 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
550 minP[d] = std::min(minP[d], surrounding_points[i][d]);
551 Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity[d]) ||
552 (surrounding_points[i][d] >= -tolerance*periodicity[d]),
553 ExcPeriodicBox(d, surrounding_points[i], periodicity[d]));
557 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
560 for (
unsigned int d=0; d<spacedim; ++d)
561 if (periodicity[d] > 0)
562 dp[d] = ( (surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0 ?
563 -periodicity[d] : 0.0 );
565 p += (surrounding_points[i]+dp)*weights[i];
569 for (
unsigned int d=0; d<spacedim; ++d)
570 if (periodicity[d] > 0)
572 p[d] += periodicity[d];
575 return project_to_manifold(surrounding_points, p);
580 template <
int dim,
int spacedim>
588 if (weights.
size(0) == 0)
591 const std::size_t n_points = surrounding_points.size();
594 for (
unsigned int d=0; d<spacedim; ++d)
595 if (periodicity[d] > 0)
596 for (
unsigned int i=0; i<n_points; ++i)
598 minP[d] = std::min(minP[d], surrounding_points[i][d]);
599 Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity[d]) ||
600 (surrounding_points[i][d] >= -tolerance*periodicity[d]),
601 ExcPeriodicBox(d, surrounding_points[i], periodicity[i]));
606 const Point<spacedim> *surrounding_points_start = surrounding_points.data();
608 boost::container::small_vector<Point<spacedim>, 200> modified_points;
609 bool adjust_periodicity =
false;
610 for (
unsigned int d=0; d<spacedim; ++d)
611 if (periodicity[d] > 0)
612 for (
unsigned int i=0; i<n_points; ++i)
613 if ((surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0)
615 adjust_periodicity =
true;
618 if (adjust_periodicity ==
true)
620 modified_points.resize(surrounding_points.size());
621 std::copy(surrounding_points.begin(), surrounding_points.end(),
622 modified_points.begin());
623 for (
unsigned int d=0; d<spacedim; ++d)
624 if (periodicity[d] > 0)
625 for (
unsigned int i=0; i<n_points; ++i)
626 if ((surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0)
627 modified_points[i][d] -= periodicity[d];
628 surrounding_points_start = modified_points.data();
632 for (
unsigned int row=0; row<weights.
size(0); ++row)
634 Assert(std::abs(std::accumulate(&weights(row,0), &weights(row,0)+n_points, 0.0)-1.0) < 1e-10,
635 ExcMessage(
"The weights for the individual points should sum to 1!"));
637 for (
unsigned int p=0; p<n_points; ++p)
638 new_point += surrounding_points_start[p] * weights(row,p);
641 for (
unsigned int d=0; d<spacedim; ++d)
642 if (periodicity[d] > 0)
643 if (new_point[d] < 0)
644 new_point[d] += periodicity[d];
648 new_points[row] = project_to_manifold(
make_array_view(surrounding_points.begin(),
649 surrounding_points.end()),
656 template <
int dim,
int spacedim>
667 template <
int dim,
int spacedim>
676 template <
int dim,
int spacedim>
687 for (
unsigned int d=0; d<spacedim; ++d)
688 if (periodicity[d] > tolerance)
690 if (direction[d] < -periodicity[d]/2)
691 direction[d] += periodicity[d];
692 else if (direction[d] > periodicity[d]/2)
693 direction[d] -= periodicity[d];
740 const Tensor<1,2> tangent = face->vertex(1) - face->vertex(0);
741 for (
unsigned int vertex=0; vertex<GeometryInfo<2>::vertices_per_face; ++vertex)
743 face_vertex_normals[vertex] =
Point<2>(tangent[1],
768 static const unsigned int neighboring_vertices[4][2]=
769 { {1,2},{3,0},{0,3},{2,1}};
770 for (
unsigned int vertex=0; vertex<vertices_per_face; ++vertex)
775 = { face->vertex(neighboring_vertices[vertex][0])
776 - face->vertex(vertex),
777 face->vertex(neighboring_vertices[vertex][1])
778 - face->vertex(vertex)
838 template <
int dim,
int spacedim>
874 const unsigned int facedim = dim-1;
877 for (
unsigned int i=0; i<facedim; ++i)
880 const double eps = 1e-12;
882 unsigned int iteration = 0;
886 for (
unsigned int v=0; v<GeometryInfo<facedim>::vertices_per_cell; ++v)
889 for (
unsigned int i=0; i<facedim; ++i)
892 for (
unsigned int v=0; v<GeometryInfo<facedim>::vertices_per_cell; ++v)
893 grad_F[i] += face->vertex(v) *
898 for (
unsigned int i=0; i<facedim; ++i)
899 for (
unsigned int j=0; j<spacedim; ++j)
900 J[i] += grad_F[i][j] * (F-p)[j];
903 for (
unsigned int i=0; i<facedim; ++i)
904 for (
unsigned int j=0; j<facedim; ++j)
905 for (
unsigned int k=0; k<spacedim; ++k)
906 H[i][j] += grad_F[i][k] * grad_F[j][k];
913 ExcMessage(
"The Newton iteration to find the reference point " 914 "did not converge in 10 iterations. Do you have a " 915 "deformed cell? (See the glossary for a definition " 916 "of what a deformed cell is. You may want to output " 917 "the vertices of your cell."));
919 if (delta_xi.
norm() < eps)
927 return internal::normalized_alternating_product(grad_F);
932 template <
int dim,
int spacedim,
int chartdim>
935 sub_manifold(periodicity)
940 template <
int dim,
int spacedim,
int chartdim>
945 const double w)
const 947 const std::array<Point<spacedim>, 2> points {{p1, p2}};
948 const std::array<double, 2> weights {{1.-w, w}};
955 template <
int dim,
int spacedim,
int chartdim>
961 const std::size_t n_points = surrounding_points.size();
963 boost::container::small_vector<Point<chartdim>, 200> chart_points(n_points);
965 for (
unsigned int i=0; i<n_points; ++i)
966 chart_points[i] = pull_back(surrounding_points[i]);
972 return push_forward(p_chart);
977 template <
int dim,
int spacedim,
int chartdim>
987 const std::size_t n_points = surrounding_points.size();
989 boost::container::small_vector<Point<chartdim>, 200> chart_points(n_points);
990 for (std::size_t i=0; i<n_points; ++i)
991 chart_points[i] = pull_back(surrounding_points[i]);
993 boost::container::small_vector<Point<chartdim>, 200> new_points_on_chart(weights.
size(0));
998 new_points_on_chart.end()));
1000 for (std::size_t row=0; row<weights.
size(0); ++row)
1001 new_points[row] = push_forward(new_points_on_chart[row]);
1006 template <
int dim,
int spacedim,
int chartdim>
1019 template <
int dim,
int spacedim,
int chartdim>
1034 ExcMessage(
"The derivative of a chart function must not be singular."));
1040 for (
unsigned int i=0; i<spacedim; ++i)
1041 result[i] += F_prime[i] * delta;
1048 template <
int dim,
int spacedim,
int chartdim>
1052 return sub_manifold.get_periodicity();
1056 #include "manifold.inst" 1058 DEAL_II_NAMESPACE_CLOSE
static ::ExceptionBase & ExcPureFunctionCalled()
static const unsigned int invalid_unsigned_int
FlatManifold(const Tensor< 1, spacedim > &periodicity=Tensor< 1, spacedim >(), const double tolerance=1e-10)
std::pair< std::array< Point< MeshIteratorType::AccessorType::space_dimension >, n_default_points_per_cell< MeshIteratorType >)>, std::array< double, n_default_points_per_cell< MeshIteratorType >)> > get_default_points_and_weights(const MeshIteratorType &iterator, const bool with_interpolation=false)
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const override
#define AssertDimension(dim1, dim2)
SymmetricTensor< 2, dim, Number > invert(const SymmetricTensor< 2, dim, Number > &t)
const Tensor< 1, spacedim > & get_periodicity() const
virtual Point< spacedim > get_new_point_on_hex(const typename Triangulation< dim, spacedim >::hex_iterator &hex) const
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &surrounding_points, const ArrayView< const double > &weights) const
numbers::NumberTraits< Number >::real_type norm() const
static Tensor< 1, dim > d_linear_shape_function_gradient(const Point< dim > &xi, const unsigned int i)
ArrayView< typename std::remove_reference< typename std::iterator_traits< Iterator >::reference >::type > make_array_view(const Iterator begin, const Iterator end)
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const
virtual DerivativeForm< 1, chartdim, spacedim > push_forward_gradient(const Point< chartdim > &chart_point) const
virtual Point< spacedim > project_to_manifold(const ArrayView< const Point< spacedim >> &surrounding_points, const Point< spacedim > &candidate) const
#define Assert(cond, exc)
numbers::NumberTraits< Number >::real_type norm_square() const
const Tensor< 1, chartdim > & get_periodicity() const
virtual Point< spacedim > project_to_manifold(const ArrayView< const Point< spacedim >> &points, const Point< spacedim > &candidate) const override
virtual std::unique_ptr< Manifold< dim, spacedim > > clone() const override
virtual Point< spacedim > get_intermediate_point(const Point< spacedim > &p1, const Point< spacedim > &p2, const double w) const
numbers::NumberTraits< Number >::real_type distance(const Point< dim, Number > &p) const
Tensor< 1, dim, Number > cross_product_3d(const Tensor< 1, dim, Number > &src1, const Tensor< 1, dim, Number > &src2)
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const override
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const override
double norm(const FEValuesBase< dim > &fe, const VectorSlice< const std::vector< std::vector< Tensor< 1, dim > > > > &Du)
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const
size_type size(const unsigned int i) const
static double d_linear_shape_function(const Point< dim > &xi, const unsigned int i)
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const override
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &surrounding_points, const ArrayView< const double > &weights) const override
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
virtual Point< spacedim > get_new_point(const ArrayView< const Point< spacedim >> &surrounding_points, const ArrayView< const double > &weights) const override
static ::ExceptionBase & ExcEmptyObject()
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Manifold< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const override
static ::ExceptionBase & ExcNotImplemented()
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const
virtual void get_new_points(const ArrayView< const Point< spacedim >> &surrounding_points, const Table< 2, double > &weights, ArrayView< Point< spacedim >> new_points) const override
ChartManifold(const Tensor< 1, chartdim > &periodicity=Tensor< 1, chartdim >())
Point< spacedim > get_new_point_on_face(const typename Triangulation< dim, spacedim >::face_iterator &face) const
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, FaceVertexNormals &face_vertex_normals) const
virtual Point< spacedim > get_intermediate_point(const Point< spacedim > &p1, const Point< spacedim > &p2, const double w) const override
static ::ExceptionBase & ExcInternalError()
Point< spacedim > get_new_point_on_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const