16 #include <deal.II/base/tensor.h> 17 #include <deal.II/base/table.h> 18 #include <deal.II/grid/manifold.h> 19 #include <deal.II/grid/tria.h> 20 #include <deal.II/grid/tria_iterator.h> 21 #include <deal.II/grid/tria_accessor.h> 22 #include <deal.II/fe/fe_q.h> 25 DEAL_II_NAMESPACE_OPEN
34 CompareWeights(
const std::vector<double> &weights)
36 compare_weights(weights)
39 bool operator() (
unsigned int a,
unsigned int b)
const 41 return compare_weights[a] < compare_weights[
b];
45 const std::vector<double> &compare_weights;
50 template <
int dim,
int spacedim>
56 template <
int dim,
int spacedim>
68 template <
int dim,
int spacedim>
75 std::vector<Point<spacedim> > vertices;
76 vertices.push_back(p1);
77 vertices.push_back(p2);
78 return project_to_manifold(vertices, w * p2 + (1-w)*p1 );
83 template <
int dim,
int spacedim>
93 template <
int dim,
int spacedim>
97 const std::vector<double> &weights)
const 99 const double tol = 1e-10;
100 const unsigned int n_points = surrounding_points.size();
103 ExcMessage(
"There should be at least one point."));
105 Assert(n_points == weights.size(),
106 ExcMessage(
"There should be as many surrounding points as weights given."));
108 Assert(std::abs(std::accumulate(weights.begin(), weights.end(), 0.0)-1.0) < tol,
109 ExcMessage(
"The weights for the individual points should sum to 1!"));
114 unsigned int permutation_short[30];
115 std::vector<unsigned int> permutation_long;
116 unsigned int *permutation;
119 permutation_long.resize(n_points);
120 permutation = &permutation_long[0];
123 permutation = &permutation_short[0];
125 for (
unsigned int i=0; i<n_points; ++i)
128 std::sort(permutation,
129 permutation + n_points,
130 CompareWeights(weights));
134 double w = weights[permutation[0]];
136 for (
unsigned int i=1; i<n_points; ++i)
139 if ( (weights[permutation[i]] + w) < tol )
142 weight = w/(weights[permutation[i]] + w);
144 if (std::abs(weight) > 1e-14)
145 p = get_intermediate_point(p, surrounding_points[permutation[i]],1.0 - weight );
146 w += weights[permutation[i]];
154 template <
int dim,
int spacedim>
162 Assert(&surrounding_points != &new_points,
163 ExcMessage(
"surrounding_points and new_points cannot be the same " 166 const unsigned int n_points = surrounding_points.size();
167 std::vector<double> local_weights(n_points);
168 for (
unsigned int row=0; row<weights.
size(0); ++row)
170 for (
unsigned int i=0; i<n_points; ++i)
171 local_weights[i] = weights(row,i);
172 new_points.push_back(get_new_point(surrounding_points, local_weights));
184 const int spacedim=2;
189 = ((p-face->vertex(0)).norm_square() > (p-face->vertex(1)).norm_square() ?
190 -get_tangent_vector(p, face->vertex(0)) :
191 get_tangent_vector(p, face->vertex(1)));
195 return normal/normal.
norm();
206 const int spacedim=3;
210 unsigned int min_index=0;
211 double min_distance = (p-face->vertex(0)).norm_square();
213 for (
unsigned int i=1; i<4; ++i)
217 if (distance < min_distance)
220 min_distance = distance;
234 if ((p-face->center()).norm_square() < min_distance)
241 t1 = get_tangent_vector(p, face->vertex(3));
242 t2 = get_tangent_vector(p, face->vertex(2));
246 t1 = get_tangent_vector(p, face->vertex(0));
247 t2 = get_tangent_vector(p, face->vertex(1));
258 t1 = get_tangent_vector(p, face->vertex(1));
259 t2 = get_tangent_vector(p, face->vertex(2));
264 t1 = get_tangent_vector(p, face->vertex(3));
265 t2 = get_tangent_vector(p, face->vertex(0));
270 t1 = get_tangent_vector(p, face->vertex(0));
271 t2 = get_tangent_vector(p, face->vertex(3));
276 t1 = get_tangent_vector(p, face->vertex(2));
277 t2 = get_tangent_vector(p, face->vertex(1));
287 return normal/normal.
norm();
292 template <
int dim,
int spacedim>
308 FaceVertexNormals &n)
const 310 n[0] = cross_product_2d(get_tangent_vector(face->vertex(0), face->vertex(1)));
311 n[1] = -cross_product_2d(get_tangent_vector(face->vertex(1), face->vertex(0)));
313 for (
unsigned int i=0; i<2; ++i)
316 "computed normals have " 328 FaceVertexNormals &n)
const 330 n[0] = cross_product_3d
331 (get_tangent_vector(face->vertex(0), face->vertex(1)),
332 get_tangent_vector(face->vertex(0), face->vertex(2)));
334 n[1] = cross_product_3d
335 (get_tangent_vector(face->vertex(1), face->vertex(3)),
336 get_tangent_vector(face->vertex(1), face->vertex(0)));
338 n[2] = cross_product_3d
339 (get_tangent_vector(face->vertex(2), face->vertex(0)),
340 get_tangent_vector(face->vertex(2), face->vertex(3)));
342 n[3] = cross_product_3d
343 (get_tangent_vector(face->vertex(3), face->vertex(2)),
344 get_tangent_vector(face->vertex(3), face->vertex(1)));
346 for (
unsigned int i=0; i<4; ++i)
349 "computed normals have " 357 template <
int dim,
int spacedim>
361 FaceVertexNormals &n)
const 363 for (
unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
365 n[v] = normal_vector(face, face->vertex(v));
372 template <
int dim,
int spacedim>
378 return get_new_point (points_weights.first,points_weights.second);
383 template <
int dim,
int spacedim>
389 return get_new_point (points_weights.first,points_weights.second);
394 template <
int dim,
int spacedim>
404 return get_new_point_on_line (face);
406 return get_new_point_on_quad (face);
414 template <
int dim,
int spacedim>
422 return get_new_point_on_line (cell);
424 return get_new_point_on_quad (cell);
426 return get_new_point_on_hex (cell);
500 template <
int dim,
int spacedim>
517 return get_new_point (points_weights.first,points_weights.second);
522 template <
int dim,
int spacedim>
527 const double epsilon = 1e-8;
529 std::vector<Point<spacedim> > q;
533 std::vector<double> w;
534 w.push_back(epsilon);
535 w.push_back(1.0-epsilon);
538 return (neighbor_point-x1)/epsilon;
544 template <
int dim,
int spacedim>
546 const double tolerance)
548 periodicity(periodicity),
554 template <
int dim,
int spacedim>
564 template <
int dim,
int spacedim>
568 const std::vector<double> &weights)
const 570 Assert(std::abs(std::accumulate(weights.begin(), weights.end(), 0.0)-1.0) < 1e-10,
571 ExcMessage(
"The weights for the individual points should sum to 1!"));
578 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
579 p += surrounding_points[i] * weights[i];
585 for (
unsigned int d=0; d<spacedim; ++d)
586 if (periodicity[d] > 0)
587 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
589 minP[d] = std::min(minP[d], surrounding_points[i][d]);
590 Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity[d]) ||
591 (surrounding_points[i][d] >= -tolerance*periodicity[d]),
592 ExcPeriodicBox(d, surrounding_points[i], periodicity[i]));
596 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
599 for (
unsigned int d=0; d<spacedim; ++d)
600 if (periodicity[d] > 0)
601 dp[d] = ( (surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0 ?
602 -periodicity[d] : 0.0 );
604 p += (surrounding_points[i]+dp)*weights[i];
608 for (
unsigned int d=0; d<spacedim; ++d)
609 if (periodicity[d] > 0)
611 p[d] += periodicity[d];
614 return project_to_manifold(surrounding_points, p);
619 template <
int dim,
int spacedim>
627 if (weights.
size(0) == 0)
630 const unsigned int n_points = surrounding_points.size();
633 for (
unsigned int d=0; d<spacedim; ++d)
634 if (periodicity[d] > 0)
635 for (
unsigned int i=0; i<n_points; ++i)
637 minP[d] = std::min(minP[d], surrounding_points[i][d]);
638 Assert( (surrounding_points[i][d] < periodicity[d]+tolerance*periodicity[d]) ||
639 (surrounding_points[i][d] >= -tolerance*periodicity[d]),
640 ExcPeriodicBox(d, surrounding_points[i], periodicity[i]));
645 const Point<spacedim> *surrounding_points_start = &surrounding_points[0];
646 std::vector<Point<spacedim> > modified_points;
647 bool adjust_periodicity =
false;
648 for (
unsigned int d=0; d<spacedim; ++d)
649 if (periodicity[d] > 0)
650 for (
unsigned int i=0; i<n_points; ++i)
651 if ((surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0)
653 adjust_periodicity =
true;
656 if (adjust_periodicity ==
true)
658 modified_points = surrounding_points;
659 for (
unsigned int d=0; d<spacedim; ++d)
660 if (periodicity[d] > 0)
661 for (
unsigned int i=0; i<n_points; ++i)
662 if ((surrounding_points[i][d]-minP[d]) > periodicity[d]/2.0)
663 modified_points[i][d] -= periodicity[d];
664 surrounding_points_start = &modified_points[0];
668 for (
unsigned int row=0; row<weights.
size(0); ++row)
670 Assert(std::abs(std::accumulate(&weights(row,0), &weights(row,0)+n_points, 0.0)-1.0) < 1e-10,
671 ExcMessage(
"The weights for the individual points should sum to 1!"));
673 for (
unsigned int p=0; p<n_points; ++p)
674 new_point += surrounding_points_start[p] * weights(row,p);
677 for (
unsigned int d=0; d<spacedim; ++d)
678 if (periodicity[d] > 0)
679 if (new_point[d] < 0)
680 new_point[d] += periodicity[d];
682 new_points.push_back(project_to_manifold(surrounding_points, new_point));
688 template <
int dim,
int spacedim>
698 template <
int dim,
int spacedim>
707 template <
int dim,
int spacedim>
718 for (
unsigned int d=0; d<spacedim; ++d)
719 if (periodicity[d] > tolerance)
721 if (direction[d] < -periodicity[d]/2)
722 direction[d] += periodicity[d];
723 else if (direction[d] > periodicity[d]/2)
724 direction[d] -= periodicity[d];
734 template <
int dim,
int spacedim,
int chartdim>
740 template <
int dim,
int spacedim,
int chartdim>
743 sub_manifold(periodicity)
748 template <
int dim,
int spacedim,
int chartdim>
758 template <
int dim,
int spacedim,
int chartdim>
762 const std::vector<double> &weights)
const 764 std::vector<Point<chartdim> > chart_points(surrounding_points.size());
766 for (
unsigned int i=0; i<surrounding_points.size(); ++i)
767 chart_points[i] = pull_back(surrounding_points[i]);
769 const Point<chartdim> p_chart = sub_manifold.get_new_point(chart_points,weights);
771 return push_forward(p_chart);
776 template <
int dim,
int spacedim,
int chartdim>
786 const unsigned int n_points = surrounding_points.size();
788 std::vector<Point<chartdim> > chart_points(n_points);
789 for (
unsigned int i=0; i<n_points; ++i)
790 chart_points[i] = pull_back(surrounding_points[i]);
792 std::vector<Point<chartdim> > new_points_on_chart;
793 new_points_on_chart.reserve(weights.
size(0));
794 sub_manifold.add_new_points(chart_points, weights, new_points_on_chart);
796 for (
unsigned int row=0; row<weights.
size(0); ++row)
797 new_points.push_back(push_forward(new_points_on_chart[row]));
802 template <
int dim,
int spacedim,
int chartdim>
815 template <
int dim,
int spacedim,
int chartdim>
830 ExcMessage(
"The derivative of a chart function must not be singular."));
836 for (
unsigned int i=0; i<spacedim; ++i)
837 result[i] += F_prime[i] * delta;
844 template <
int dim,
int spacedim,
int chartdim>
848 return sub_manifold.get_periodicity();
852 #include "manifold.inst" 854 DEAL_II_NAMESPACE_CLOSE
virtual void add_new_points(const std::vector< Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, std::vector< Point< spacedim > > &new_points) const
static ::ExceptionBase & ExcPureFunctionCalled()
FlatManifold(const Tensor< 1, spacedim > &periodicity=Tensor< 1, spacedim >(), const double tolerance=1e-10)
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const
#define AssertDimension(dim1, dim2)
const std::vector< Point< dim > > & get_points() const
const std::vector< double > & get_weights() const
const Tensor< 1, spacedim > & get_periodicity() const
virtual Point< spacedim > get_new_point_on_hex(const typename Triangulation< dim, spacedim >::hex_iterator &hex) const
#define AssertIndexRange(index, range)
std::pair< std::vector< Point< MeshIteratorType::AccessorType::space_dimension > >, std::vector< double > > get_default_points_and_weights(const MeshIteratorType &iterator, const bool with_laplace=false)
numbers::NumberTraits< Number >::real_type norm() const
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const 1
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 Point< spacedim > project_to_manifold(const std::vector< Point< spacedim > > &points, const Point< spacedim > &candidate) const
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 void add_new_points(const std::vector< Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, std::vector< Point< spacedim > > &new_points) const
#define Assert(cond, exc)
virtual Point< spacedim > project_to_manifold(const std::vector< Point< spacedim > > &surrounding_points, const Point< spacedim > &candidate) const
numbers::NumberTraits< Number >::real_type norm_square() const
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const 1
const Tensor< 1, chartdim > & get_periodicity() const
virtual Point< spacedim > get_intermediate_point(const Point< spacedim > &p1, const Point< spacedim > &p2, const double w) const
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
virtual Tensor< 1, spacedim > get_tangent_vector(const Point< spacedim > &x1, const Point< spacedim > &x2) const
virtual void add_new_points(const std::vector< Point< spacedim > > &surrounding_points, const Table< 2, double > &weights, std::vector< Point< spacedim > > &new_points) const
double norm(const FEValuesBase< dim > &fe, const VectorSlice< const std::vector< std::vector< Tensor< 1, dim > > > > &Du)
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const 1
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
static ::ExceptionBase & ExcEmptyObject()
unsigned int size(const unsigned int i) const
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const
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
static ::ExceptionBase & ExcInternalError()
Point< spacedim > get_new_point_on_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell) const