Reference documentation for deal.II version 8.5.1
tria_boundary_lib.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/grid/tria_boundary_lib.h>
17 #include <deal.II/grid/tria.h>
18 #include <deal.II/grid/tria_iterator.h>
19 #include <deal.II/grid/tria_accessor.h>
20 #include <deal.II/base/tensor.h>
21 #include <cmath>
22 
23 
24 
25 DEAL_II_NAMESPACE_OPEN
26 
27 
28 
29 template <int dim, int spacedim>
31  const unsigned int axis)
32  :
33  radius(radius),
34  direction (get_axis_vector (axis)),
35  point_on_axis (Point<spacedim>())
36 {}
37 
38 
39 template <int dim, int spacedim>
41  const Point<spacedim> &direction,
42  const Point<spacedim> &point_on_axis)
43  :
44  radius(radius),
45  direction (direction / direction.norm()),
46  point_on_axis (point_on_axis)
47 {}
48 
49 
50 template <int dim, int spacedim>
53 {
54  Assert (axis < spacedim, ExcIndexRange (axis, 0, spacedim));
55 
56  Point<spacedim> axis_vector;
57  axis_vector[axis] = 1;
58  return axis_vector;
59 }
60 
61 
62 
63 template <int dim, int spacedim>
66 get_new_point_on_line (const typename Triangulation<dim,spacedim>::line_iterator &line) const
67 {
68  // compute a proposed new point
70 
71  // we then have to project this
72  // point out to the given radius
73  // from the axis. to this end, we
74  // have to take into account the
75  // offset point_on_axis and the
76  // direction of the axis
77  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
78  ((middle-point_on_axis) * direction) * direction;
79  // scale it to the desired length
80  // and put everything back
81  // together, unless we have a point
82  // on the axis
83  if (vector_from_axis.norm() <= 1e-10 * middle.norm())
84  return middle;
85  else
86  return Point<spacedim>(vector_from_axis / vector_from_axis.norm() * radius +
87  ((middle-point_on_axis) * direction) * direction +
88  point_on_axis);
89 }
90 
91 
92 
93 template<>
96 get_new_point_on_quad (const Triangulation<3>::quad_iterator &quad) const
97 {
99 
100  // same algorithm as above
101  const unsigned int spacedim = 3;
102 
103  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
104  ((middle-point_on_axis) * direction) * direction;
105  if (vector_from_axis.norm() <= 1e-10 * middle.norm())
106  return middle;
107  else
108  return Point<3>(vector_from_axis / vector_from_axis.norm() * radius +
109  ((middle-point_on_axis) * direction) * direction +
110  point_on_axis);
111 }
112 
113 template<>
114 Point<3>
116 get_new_point_on_quad (const Triangulation<2,3>::quad_iterator &quad) const
117 {
119 
120  // same algorithm as above
121  const unsigned int spacedim = 3;
122  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
123  ((middle-point_on_axis) * direction) * direction;
124  if (vector_from_axis.norm() <= 1e-10 * middle.norm())
125  return middle;
126  else
127  return Point<3>(vector_from_axis / vector_from_axis.norm() * radius +
128  ((middle-point_on_axis) * direction) * direction +
129  point_on_axis);
130 }
131 
132 
133 template <int dim, int spacedim>
136 get_new_point_on_quad (const typename Triangulation<dim,spacedim>::quad_iterator &) const
137 {
138  Assert (false, ExcImpossibleInDim(dim));
139  return Point<spacedim>();
140 }
141 
142 
143 
144 template <int dim, int spacedim>
145 void
147  const typename Triangulation<dim,spacedim>::line_iterator &line,
148  std::vector<Point<spacedim> > &points) const
149 {
150  if (points.size()==1)
151  points[0]=get_new_point_on_line(line);
152  else
153  get_intermediate_points_between_points(line->vertex(0), line->vertex(1), points);
154 }
155 
156 
157 template <int dim, int spacedim>
158 void
160  const Point<spacedim> &v0,
161  const Point<spacedim> &v1,
162  std::vector<Point<spacedim> > &points) const
163 {
164  const unsigned int n=points.size();
165  Assert(n>0, ExcInternalError());
166 
167  // Do a simple linear interpolation followed by projection, using the same
168  // algorithm as above
169  const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
170 
171  for (unsigned int i=0; i<n; ++i)
172  {
173  const double x = line_points[i+1][0];
174  const Point<spacedim> middle = (1-x)*v0 + x*v1;
175 
176  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
177  ((middle-point_on_axis) * direction) * direction;
178  if (vector_from_axis.norm() <= 1e-10 * middle.norm())
179  points[i] = middle;
180  else
181  points[i] = Point<spacedim>(vector_from_axis / vector_from_axis.norm() * radius +
182  ((middle-point_on_axis) * direction) * direction +
183  point_on_axis);
184  }
185 }
186 
187 
188 
189 template <>
190 void
192  const Triangulation<3>::quad_iterator &quad,
193  std::vector<Point<3> > &points) const
194 {
195  if (points.size()==1)
196  points[0]=get_new_point_on_quad(quad);
197  else
198  {
199  unsigned int m=static_cast<unsigned int> (std::sqrt(static_cast<double>(points.size())));
200  Assert(points.size()==m*m, ExcInternalError());
201 
202  std::vector<Point<3> > lp0(m);
203  std::vector<Point<3> > lp1(m);
204 
205  get_intermediate_points_on_line(quad->line(0), lp0);
206  get_intermediate_points_on_line(quad->line(1), lp1);
207 
208  std::vector<Point<3> > lps(m);
209  for (unsigned int i=0; i<m; ++i)
210  {
211  get_intermediate_points_between_points(lp0[i], lp1[i], lps);
212 
213  for (unsigned int j=0; j<m; ++j)
214  points[i*m+j]=lps[j];
215  }
216  }
217 }
218 
219 
220 
221 template <int dim, int spacedim>
222 void
224  const typename Triangulation<dim,spacedim>::quad_iterator &,
225  std::vector<Point<spacedim> > &) const
226 {
227  Assert (false, ExcImpossibleInDim(dim));
228 }
229 
230 
231 
232 
233 template <>
234 void
238 {
239  Assert (false, ExcImpossibleInDim(1));
240 }
241 
242 
243 
244 
245 template <int dim, int spacedim>
246 void
249  typename Boundary<dim,spacedim>::FaceVertexNormals &face_vertex_normals) const
250 {
251  for (unsigned int v=0; v<GeometryInfo<dim>::vertices_per_face; ++v)
252  {
253  const Point<spacedim> vertex = face->vertex(v);
254 
255  const Tensor<1,spacedim> vector_from_axis = (vertex-point_on_axis) -
256  ((vertex-point_on_axis) * direction) * direction;
257 
258  face_vertex_normals[v] = (vector_from_axis / vector_from_axis.norm());
259  }
260 }
261 
262 
263 
264 template <int dim, int spacedim>
265 double
267 {
268  return radius;
269 }
270 
271 
272 //======================================================================//
273 
274 template<int dim>
275 ConeBoundary<dim>::ConeBoundary (const double radius_0,
276  const double radius_1,
277  const Point<dim> x_0,
278  const Point<dim> x_1)
279  :
280  radius_0 (radius_0),
281  radius_1 (radius_1),
282  x_0 (x_0),
283  x_1 (x_1)
284 {}
285 
286 
287 
288 template<int dim>
290 {
291  for (unsigned int i = 0; i < dim; ++i)
292  if ((x_1 (i) - x_0 (i)) != 0)
293  return (radius_1 - radius_0) * (x (i) - x_0 (i)) / (x_1 (i) - x_0 (i)) + radius_0;
294 
295  return 0;
296 }
297 
298 
299 
300 template<int dim>
301 void
304  const Point<dim> &p1,
305  std::vector<Point<dim> > &points) const
306 {
307  const unsigned int n = points.size ();
308  const Tensor<1,dim> axis = x_1 - x_0;
309 
310  Assert (n > 0, ExcInternalError ());
311 
312  const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
313 
314  for (unsigned int i=0; i<n; ++i)
315  {
316  const double x = line_points[i+1][0];
317 
318  // Compute the current point.
319  const Point<dim> x_i = (1-x)*p0 + x*p1;
320  // To project this point on the boundary of the cone we first compute
321  // the orthogonal projection of this point onto the axis of the cone.
322  const double c = (x_i - x_0) * axis / (axis*axis);
323  const Point<dim> x_ip = x_0 + c * axis;
324  // Compute the projection of the middle point on the boundary of the
325  // cone.
326  points[i] = x_ip + get_radius (x_ip) * (x_i - x_ip) / (x_i - x_ip).norm ();
327  }
328 }
329 
330 template<int dim>
334 {
335  const Tensor<1,dim> axis = x_1 - x_0;
336  // Compute the middle point of the line.
338  // To project it on the boundary of the cone we first compute the orthogonal
339  // projection of the middle point onto the axis of the cone.
340  const double c = (middle - x_0) * axis / (axis*axis);
341  const Point<dim> middle_p = x_0 + c * axis;
342  // Compute the projection of the middle point on the boundary of the cone.
343  return middle_p + get_radius (middle_p) * (middle - middle_p) / (middle - middle_p).norm ();
344 }
345 
346 
347 
348 template <>
349 Point<3>
351 get_new_point_on_quad (const Triangulation<3>::quad_iterator &quad) const
352 {
353  const int dim = 3;
354 
355  const Tensor<1,dim> axis = x_1 - x_0;
356  // Compute the middle point of the quad.
358  // Same algorithm as above: To project it on the boundary of the cone we
359  // first compute the orthogonal projection of the middle point onto the axis
360  // of the cone.
361  const double c = (middle - x_0) * axis / (axis*axis);
362  const Point<dim> middle_p = x_0 + c * axis;
363  // Compute the projection of the middle point on the boundary of the cone.
364  return middle_p + get_radius (middle_p) * (middle - middle_p) / (middle - middle_p).norm ();
365 }
366 
367 
368 
369 template<int dim>
373 {
374  Assert (false, ExcImpossibleInDim (dim));
375 
376  return Point<dim>();
377 }
378 
379 
380 
381 template<int dim>
382 void
385  std::vector<Point<dim> > &points) const
386 {
387  if (points.size () == 1)
388  points[0] = get_new_point_on_line (line);
389  else
390  get_intermediate_points_between_points (line->vertex (0), line->vertex (1), points);
391 }
392 
393 
394 
395 
396 template<>
397 void
399 get_intermediate_points_on_quad (const Triangulation<3>::quad_iterator &quad,
400  std::vector<Point<3> > &points) const
401 {
402  if (points.size () == 1)
403  points[0] = get_new_point_on_quad (quad);
404  else
405  {
406  unsigned int n = static_cast<unsigned int> (std::sqrt (static_cast<double> (points.size ())));
407 
408  Assert (points.size () == n * n, ExcInternalError ());
409 
410  std::vector<Point<3> > points_line_0 (n);
411  std::vector<Point<3> > points_line_1 (n);
412 
413  get_intermediate_points_on_line (quad->line (0), points_line_0);
414  get_intermediate_points_on_line (quad->line (1), points_line_1);
415 
416  std::vector<Point<3> > points_line_segment (n);
417 
418  for (unsigned int i = 0; i < n; ++i)
419  {
420  get_intermediate_points_between_points (points_line_0[i],
421  points_line_1[i],
422  points_line_segment);
423 
424  for (unsigned int j = 0; j < n; ++j)
425  points[i * n + j] = points_line_segment[j];
426  }
427  }
428 }
429 
430 
431 
432 template <int dim>
433 void
436  std::vector<Point<dim> > &) const
437 {
438  Assert (false, ExcImpossibleInDim (dim));
439 }
440 
441 
442 
443 
444 template<>
445 void
449 {
450  Assert (false, ExcImpossibleInDim (1));
451 }
452 
453 
454 
455 template<int dim>
456 void
459  typename Boundary<dim>::FaceVertexNormals &face_vertex_normals) const
460 {
461  const Tensor<1,dim> axis = x_1 - x_0;
462 
463  for (unsigned int vertex = 0; vertex < GeometryInfo<dim>::vertices_per_face; ++vertex)
464  {
465  // Compute the orthogonal projection of the vertex onto the axis of the
466  // cone.
467  const double c = (face->vertex (vertex) - x_0) * axis / (axis*axis);
468  const Point<dim> vertex_p = x_0 + c * axis;
469  // Then compute the vector pointing from the point <tt>vertex_p</tt> on
470  // the axis to the vertex.
471  const Tensor<1,dim> axis_to_vertex = face->vertex (vertex) - vertex_p;
472 
473  face_vertex_normals[vertex] = axis_to_vertex / axis_to_vertex.norm ();
474  }
475 }
476 
477 
478 //======================================================================//
479 
480 template <int dim, int spacedim>
482  const double radius)
483  :
484  center(p),
485  radius(radius),
486  compute_radius_automatically(false)
487 {}
488 
489 
490 
491 template <int dim, int spacedim>
493 HyperBallBoundary<dim,spacedim>::get_new_point_on_line (const typename Triangulation<dim,spacedim>::line_iterator &line) const
494 {
496 
497  middle -= center;
498 
499  double r=0;
500  if (compute_radius_automatically)
501  r = (line->vertex(0) - center).norm();
502  else
503  r = radius;
504 
505  // project to boundary
506  middle *= r / std::sqrt(middle.square());
507  middle += center;
508  return middle;
509 }
510 
511 
512 
513 template <>
514 Point<1>
516 get_new_point_on_quad (const Triangulation<1,1>::quad_iterator &) const
517 {
518  Assert (false, ExcInternalError());
519  return Point<1>();
520 }
521 
522 
523 template <>
524 Point<2>
526 get_new_point_on_quad (const Triangulation<1,2>::quad_iterator &) const
527 {
528  Assert (false, ExcInternalError());
529  return Point<2>();
530 }
531 
532 
533 
534 template <int dim, int spacedim>
537 get_new_point_on_quad (const typename Triangulation<dim,spacedim>::quad_iterator &quad) const
538 {
540 
541  middle -= center;
542 
543  double r=0;
544  if (compute_radius_automatically)
545  r = (quad->vertex(0) - center).norm();
546  else
547  r = radius;
548 
549  // project to boundary
550  middle *= r / std::sqrt(middle.square());
551 
552  middle += center;
553  return middle;
554 }
555 
556 
557 
558 template <>
559 void
561  const Triangulation<1>::line_iterator &,
562  std::vector<Point<1> > &) const
563 {
564  Assert (false, ExcImpossibleInDim(1));
565 }
566 
567 
568 
569 template <int dim, int spacedim>
570 void
572  const typename Triangulation<dim,spacedim>::line_iterator &line,
573  std::vector<Point<spacedim> > &points) const
574 {
575  if (points.size()==1)
576  points[0]=get_new_point_on_line(line);
577  else
578  get_intermediate_points_between_points(line->vertex(0), line->vertex(1), points);
579 }
580 
581 
582 
583 template <int dim, int spacedim>
584 void
586  const Point<spacedim> &p0, const Point<spacedim> &p1,
587  std::vector<Point<spacedim> > &points) const
588 {
589  const unsigned int n=points.size();
590  Assert(n>0, ExcInternalError());
591 
592  const Tensor<1,spacedim> v0=p0-center,
593  v1=p1-center;
594  const double length=(v1-v0).norm();
595 
596  double eps=1e-12;
597  (void)eps;
598  double r=0;
599  if (compute_radius_automatically)
600  r = (p0 - center).norm();
601  else
602  r = radius;
603 
604  Assert((std::fabs(v0*v0-r*r)<eps*r*r)
605  &&
606  (std::fabs(v1*v1-r*r)<eps*r*r),
607  ExcMessage("In computing the location of midpoints of an edge of a "
608  "HyperBallBoundary, one of the vertices of the edge "
609  "does not have the expected distance from the center "
610  "of the sphere. This may happen if the geometry has "
611  "been deformed, or if the HyperBallBoundary object has "
612  "been assigned to a part of the boundary that is not "
613  "in fact a sphere (e.g., the sides of a quarter shell "
614  "or one octant of a ball)."));
615 
616  const double alpha=std::acos((v0*v1)/std::sqrt((v0*v0)*(v1*v1)));
617  const Tensor<1,spacedim> pm=0.5*(v0+v1);
618 
619  const double h=pm.norm();
620 
621  // n even: m=n/2,
622  // n odd: m=(n-1)/2
623  const std::vector<Point<1> > &line_points = this->get_line_support_points(n);
624  const unsigned int m=n/2;
625  for (unsigned int i=0; i<m ; ++i)
626  {
627  const double beta = alpha * (line_points[i+1][0]-0.5);
628  const double d = h*std::tan(beta);
629  points[i] = Point<spacedim>(pm+d/length*(v1-v0));
630  points[n-1-i] = Point<spacedim>(pm-d/length*(v1-v0));
631  }
632 
633  if ((n+1)%2==0)
634  // if the number of parts is even insert the midpoint
635  points[(n-1)/2] = Point<spacedim>(pm);
636 
637 
638  // project the points from the straight line to the HyperBallBoundary
639  for (unsigned int i=0; i<n; ++i)
640  {
641  points[i] *= r / std::sqrt(points[i].square());
642  points[i] += center;
643  }
644 }
645 
646 
647 
648 template <>
649 void
651  const Triangulation<3>::quad_iterator &quad,
652  std::vector<Point<3> > &points) const
653 {
654  if (points.size()==1)
655  points[0]=get_new_point_on_quad(quad);
656  else
657  {
658  unsigned int m=static_cast<unsigned int> (std::sqrt(static_cast<double>(points.size())));
659  Assert(points.size()==m*m, ExcInternalError());
660 
661  std::vector<Point<3> > lp0(m);
662  std::vector<Point<3> > lp1(m);
663 
664  get_intermediate_points_on_line(quad->line(0), lp0);
665  get_intermediate_points_on_line(quad->line(1), lp1);
666 
667  std::vector<Point<3> > lps(m);
668  for (unsigned int i=0; i<m; ++i)
669  {
670  get_intermediate_points_between_points(lp0[i], lp1[i], lps);
671 
672  for (unsigned int j=0; j<m; ++j)
673  points[i*m+j]=lps[j];
674  }
675  }
676 }
677 
678 
679 
680 template <>
681 void
683  const Triangulation<2,3>::quad_iterator &quad,
684  std::vector<Point<3> > &points) const
685 {
686  if (points.size()==1)
687  points[0]=get_new_point_on_quad(quad);
688  else
689  {
690  unsigned int m=static_cast<unsigned int> (std::sqrt(static_cast<double>(points.size())));
691  Assert(points.size()==m*m, ExcInternalError());
692 
693  std::vector<Point<3> > lp0(m);
694  std::vector<Point<3> > lp1(m);
695 
696  get_intermediate_points_on_line(quad->line(0), lp0);
697  get_intermediate_points_on_line(quad->line(1), lp1);
698 
699  std::vector<Point<3> > lps(m);
700  for (unsigned int i=0; i<m; ++i)
701  {
702  get_intermediate_points_between_points(lp0[i], lp1[i], lps);
703 
704  for (unsigned int j=0; j<m; ++j)
705  points[i*m+j]=lps[j];
706  }
707  }
708 }
709 
710 
711 
712 template <int dim, int spacedim>
713 void
715  const typename Triangulation<dim,spacedim>::quad_iterator &,
716  std::vector<Point<spacedim> > &) const
717 {
718  Assert(false, ExcImpossibleInDim(dim));
719 }
720 
721 
722 
723 template <int dim, int spacedim>
727  const Point<spacedim> &p) const
728 {
729  const Tensor<1,spacedim> unnormalized_normal = p-center;
730  return unnormalized_normal/unnormalized_normal.norm();
731 }
732 
733 
734 
735 template <>
736 void
740 {
741  Assert (false, ExcImpossibleInDim(1));
742 }
743 
744 template <>
745 void
749 {
750  Assert (false, ExcImpossibleInDim(1));
751 }
752 
753 
754 
755 template <int dim, int spacedim>
756 void
759  typename Boundary<dim,spacedim>::FaceVertexNormals &face_vertex_normals) const
760 {
761  for (unsigned int vertex=0; vertex<GeometryInfo<dim>::vertices_per_face; ++vertex)
762  face_vertex_normals[vertex] = face->vertex(vertex)-center;
763 }
764 
765 
766 
767 template <int dim, int spacedim>
770 {
771  return center;
772 }
773 
774 
775 
776 template <int dim, int spacedim>
777 double
779 {
780  Assert(!compute_radius_automatically, ExcRadiusNotSet());
781  return radius;
782 }
783 
784 
785 /* ---------------------------------------------------------------------- */
786 
787 
788 template <int dim>
790  const double radius) :
791  HyperBallBoundary<dim> (center, radius)
792 {}
793 
794 
795 
796 template <int dim>
800 {
801  // check whether center of object is at x==x_center, since then it belongs
802  // to the plane part of the boundary. however, this is not the case if it is
803  // at the outer perimeter
804  const Point<dim> line_center = line->center();
805  const Point<dim> vertices[2] = { line->vertex(0), line->vertex(1) };
806 
807  if ((line_center(0) == this->center(0))
808  &&
809  ((std::fabs(vertices[0].distance(this->center)-this->radius) >
810  1e-5*this->radius)
811  ||
812  (std::fabs(vertices[1].distance(this->center)-this->radius) >
813  1e-5*this->radius)))
814  return line_center;
815  else
817 }
818 
819 
820 
821 template <>
822 Point<1>
824 get_new_point_on_quad (const Triangulation<1>::quad_iterator &) const
825 {
826  Assert (false, ExcInternalError());
827  return Point<1>();
828 }
829 
830 
831 
832 template <int dim>
836 {
837  const Point<dim> quad_center = quad->center();
838  if (quad_center(0) == this->center(0))
839  return quad_center;
840  else
842 }
843 
844 
845 
846 template <int dim>
847 void
850  std::vector<Point<dim> > &points) const
851 {
852  // check whether center of object is at x==0, since then it belongs to the
853  // plane part of the boundary
854  const Point<dim> line_center = line->center();
855  if (line_center(0) == this->center(0))
857  else
859 }
860 
861 
862 
863 template <int dim>
864 void
867  std::vector<Point<dim> > &points) const
868 {
869  if (points.size()==1)
870  points[0]=get_new_point_on_quad(quad);
871  else
872  {
873  // check whether center of object is at x==0, since then it belongs to
874  // the plane part of the boundary
875  const Point<dim> quad_center = quad->center();
876  if (quad_center(0) == this->center(0))
878  else
880  }
881 }
882 
883 
884 
885 template <>
886 void
888 get_intermediate_points_on_quad (const Triangulation<1>::quad_iterator &,
889  std::vector<Point<1> > &) const
890 {
891  Assert (false, ExcInternalError());
892 }
893 
894 
895 
896 template <>
897 void
901 {
902  Assert (false, ExcImpossibleInDim(1));
903 }
904 
905 
906 
907 template <int dim>
908 void
911  typename Boundary<dim>::FaceVertexNormals &face_vertex_normals) const
912 {
913  // check whether center of object is at x==0, since then it belongs to the
914  // plane part of the boundary
915  const Point<dim> quad_center = face->center();
916  if (quad_center(0) == this->center(0))
917  StraightBoundary<dim>::get_normals_at_vertices (face, face_vertex_normals);
918  else
919  HyperBallBoundary<dim>::get_normals_at_vertices (face, face_vertex_normals);
920 }
921 
922 
923 /* ---------------------------------------------------------------------- */
924 
925 
926 
927 template <int dim>
929  :
930  HyperBallBoundary<dim>(center, 0.)
931 {
932  this->compute_radius_automatically=true;
933 }
934 
935 
936 /* ---------------------------------------------------------------------- */
937 
938 
939 
940 
941 template <int dim>
943  const double inner_radius,
944  const double outer_radius)
945  :
946  HyperShellBoundary<dim> (center),
947  inner_radius (inner_radius),
948  outer_radius (outer_radius)
949 {
950  if (dim > 2)
951  Assert ((inner_radius >= 0) &&
952  (outer_radius > 0) &&
953  (outer_radius > inner_radius),
954  ExcMessage ("Inner and outer radii must be specified explicitly in 3d."));
955 }
956 
957 
958 
959 template <int dim>
963 {
964  switch (dim)
965  {
966  // in 2d, first check whether the two end points of the line are on the
967  // axis of symmetry. if so, then return the mid point
968  case 2:
969  {
970  if ((line->vertex(0)(0) == this->center(0))
971  &&
972  (line->vertex(1)(0) == this->center(0)))
973  return (line->vertex(0) + line->vertex(1))/2;
974  else
975  // otherwise we are on the outer or inner part of the shell. proceed
976  // as in the base class
978  }
979 
980  // in 3d, a line is a straight line if it is on the symmetry plane and if
981  // not both of its end points are on either the inner or outer sphere
982  case 3:
983  {
984 
985  if (((line->vertex(0)(0) == this->center(0))
986  &&
987  (line->vertex(1)(0) == this->center(0)))
988  &&
989  !(((std::fabs (line->vertex(0).distance (this->center)
990  - inner_radius) < 1e-12 * outer_radius)
991  &&
992  (std::fabs (line->vertex(1).distance (this->center)
993  - inner_radius) < 1e-12 * outer_radius))
994  ||
995  ((std::fabs (line->vertex(0).distance (this->center)
996  - outer_radius) < 1e-12 * outer_radius)
997  &&
998  (std::fabs (line->vertex(1).distance (this->center)
999  - outer_radius) < 1e-12 * outer_radius))))
1000  return (line->vertex(0) + line->vertex(1))/2;
1001  else
1002  // otherwise we are on the outer or inner part of the shell. proceed
1003  // as in the base class
1005  }
1006 
1007  default:
1008  Assert (false, ExcNotImplemented());
1009  }
1010 
1011  return Point<dim>();
1012 }
1013 
1014 
1015 
1016 template <>
1017 Point<1>
1019 get_new_point_on_quad (const Triangulation<1>::quad_iterator &) const
1020 {
1021  Assert (false, ExcInternalError());
1022  return Point<1>();
1023 }
1024 
1025 
1026 
1027 
1028 template <int dim>
1029 Point<dim>
1032 {
1033  // if this quad is on the symmetry plane, take the center point and project
1034  // it outward to the same radius as the centers of the two radial lines
1035  if ((quad->vertex(0)(0) == this->center(0)) &&
1036  (quad->vertex(1)(0) == this->center(0)) &&
1037  (quad->vertex(2)(0) == this->center(0)) &&
1038  (quad->vertex(3)(0) == this->center(0)))
1039  {
1040  const Point<dim> quad_center = (quad->vertex(0) + quad->vertex(1) +
1041  quad->vertex(2) + quad->vertex(3) )/4;
1042  const Tensor<1,dim> quad_center_offset = quad_center - this->center;
1043 
1044 
1045  if (std::fabs (quad->line(0)->center().distance(this->center) -
1046  quad->line(1)->center().distance(this->center))
1047  < 1e-12 * outer_radius)
1048  {
1049  // lines 0 and 1 are radial
1050  const double needed_radius
1051  = quad->line(0)->center().distance(this->center);
1052 
1053  return (this->center +
1054  quad_center_offset/quad_center_offset.norm() * needed_radius);
1055  }
1056  else if (std::fabs (quad->line(2)->center().distance(this->center) -
1057  quad->line(3)->center().distance(this->center))
1058  < 1e-12 * outer_radius)
1059  {
1060  // lines 2 and 3 are radial
1061  const double needed_radius
1062  = quad->line(2)->center().distance(this->center);
1063 
1064  return (this->center +
1065  quad_center_offset/quad_center_offset.norm() * needed_radius);
1066  }
1067  else
1068  Assert (false, ExcInternalError());
1069  }
1070 
1071  // otherwise we are on the outer or inner part of the shell. proceed as in
1072  // the base class
1074 }
1075 
1076 
1077 
1078 template <int dim>
1079 void
1082  std::vector<Point<dim> > &points) const
1083 {
1084  switch (dim)
1085  {
1086  // in 2d, first check whether the two end points of the line are on the
1087  // axis of symmetry. if so, then return the mid point
1088  case 2:
1089  {
1090  if ((line->vertex(0)(0) == this->center(0))
1091  &&
1092  (line->vertex(1)(0) == this->center(0)))
1094  else
1095  // otherwise we are on the outer or inner part of the shell. proceed
1096  // as in the base class
1098  break;
1099  }
1100 
1101  // in 3d, a line is a straight line if it is on the symmetry plane and if
1102  // not both of its end points are on either the inner or outer sphere
1103  case 3:
1104  {
1105  if (((line->vertex(0)(0) == this->center(0))
1106  &&
1107  (line->vertex(1)(0) == this->center(0)))
1108  &&
1109  !(((std::fabs (line->vertex(0).distance (this->center)
1110  - inner_radius) < 1e-12 * outer_radius)
1111  &&
1112  (std::fabs (line->vertex(1).distance (this->center)
1113  - inner_radius) < 1e-12 * outer_radius))
1114  ||
1115  ((std::fabs (line->vertex(0).distance (this->center)
1116  - outer_radius) < 1e-12 * outer_radius)
1117  &&
1118  (std::fabs (line->vertex(1).distance (this->center)
1119  - outer_radius) < 1e-12 * outer_radius))))
1121  else
1122  // otherwise we are on the outer or inner part of the shell. proceed
1123  // as in the base class
1125 
1126  break;
1127  }
1128 
1129  default:
1130  Assert (false, ExcNotImplemented());
1131  }
1132 }
1133 
1134 
1135 
1136 template <int dim>
1137 void
1140  std::vector<Point<dim> > &points) const
1141 {
1142  Assert (dim < 3, ExcNotImplemented());
1143 
1144  // check whether center of object is at x==0, since then it belongs to the
1145  // plane part of the boundary
1146  const Point<dim> quad_center = quad->center();
1147  if (quad_center(0) == this->center(0))
1149  else
1151 }
1152 
1153 
1154 
1155 template <>
1156 void
1158 get_intermediate_points_on_quad (const Triangulation<1>::quad_iterator &,
1159  std::vector<Point<1> > &) const
1160 {
1161  Assert (false, ExcInternalError());
1162 }
1163 
1164 
1165 
1166 template <>
1167 void
1171 {
1172  Assert (false, ExcImpossibleInDim(1));
1173 }
1174 
1175 
1176 
1177 
1178 
1179 template <int dim>
1180 void
1183  typename Boundary<dim>::FaceVertexNormals &face_vertex_normals) const
1184 {
1185  if (face->center()(0) == this->center(0))
1186  StraightBoundary<dim>::get_normals_at_vertices (face, face_vertex_normals);
1187  else
1188  HyperShellBoundary<dim>::get_normals_at_vertices (face, face_vertex_normals);
1189 }
1190 
1191 
1192 
1193 
1194 template <int dim, int spacedim>
1196  const double r__)
1197  :
1198  R(R__),
1199  r(r__)
1200 {
1201  Assert (false, ExcNotImplemented());
1202 }
1203 
1204 
1205 
1206 template <>
1207 TorusBoundary<2,3>::TorusBoundary (const double R__,
1208  const double r__)
1209  :
1210  R(R__),
1211  r(r__)
1212 {
1213  Assert (R>r, ExcMessage("Outer radius must be greater than inner radius."));
1214 }
1215 
1216 
1217 
1218 template <int dim, int spacedim>
1219 double
1221  const double x,
1222  const double y) const
1223 {
1224  if (y>=0)
1225  {
1226  if (x >=0)
1227  return angle;
1228 
1229  return numbers::PI-angle;
1230  }
1231 
1232  if (x <=0)
1233  return numbers::PI+angle;
1234 
1235  return 2.0*numbers::PI-angle;
1236 }
1237 
1238 
1239 
1240 template <>
1241 Point<3>
1242 TorusBoundary<2,3>::get_real_coord (const Point<2> &surfP) const
1243 {
1244  const double theta=surfP(0);
1245  const double phi=surfP(1);
1246 
1247  return Point<3> ((R+r*std::cos(phi))*std::cos(theta),
1248  r*std::sin(phi),
1249  (R+r*std::cos(phi))*std::sin(theta));
1250 }
1251 
1252 
1253 
1254 template <>
1255 Point<2>
1257 {
1258  const double phi=std::asin(std::abs(p(1))/r);
1259  const double Rr_2=p(0)*p(0)+p(2)*p(2);
1260 
1261  Point<2> surfP;
1262  surfP(1)=get_correct_angle(phi,Rr_2-R*R,p(1));//phi
1263 
1264  if (std::abs(p(0))<1.E-5)
1265  {
1266  if (p(2)>=0)
1267  surfP(0) = numbers::PI*0.5;
1268  else
1269  surfP(0) = -numbers::PI*0.5;
1270  }
1271  else
1272  {
1273  const double theta = std::atan(std::abs(p(2)/p(0)));
1274  surfP(0)= get_correct_angle(theta,p(0),p(2));
1275  }
1276 
1277  return surfP;
1278 }
1279 
1280 
1281 
1282 template <>
1283 Point<3>
1284 TorusBoundary<2,3>::get_new_point_on_line (const Triangulation<2,3>::line_iterator &line) const
1285 {
1286  //Just get the average
1287  Point<2> p0=get_surf_coord(line->vertex(0));
1288  Point<2> p1=get_surf_coord(line->vertex(1));
1289 
1290  Point<2> middle(0,0);
1291 
1292  //Take care for periodic conditions, For instance phi0= 0, phi1= 3/2*Pi
1293  //middle has to be 7/4*Pi not 3/4*Pi. This also works for -Pi/2 + Pi, middle
1294  //is 5/4*Pi
1295  for (unsigned int i=0; i<2; i++)
1296  if (std::abs(p0(i)-p1(i))> numbers::PI)
1297  middle(i)=2*numbers::PI;
1298 
1299  middle+= p0 + p1;
1300  middle*=0.5;
1301 
1302  Point<3> midReal=get_real_coord(middle);
1303  return midReal;
1304 }
1305 
1306 
1307 
1308 template <>
1309 Point<3>
1310 TorusBoundary<2,3>::get_new_point_on_quad (const Triangulation<2,3>::quad_iterator &quad) const
1311 {
1312  //Just get the average
1313  Point<2> p[4];
1314 
1315  for (unsigned int i=0; i<4; i++)
1316  p[i]=get_surf_coord(quad->vertex(i));
1317 
1318  Point<2> middle(0,0);
1319 
1320  //Take care for periodic conditions, see get_new_point_on_line() above
1321  //For instance phi0= 0, phi1= 3/2*Pi middle has to be 7/4*Pi not 3/4*Pi
1322  //This also works for -Pi/2 + Pi + Pi- Pi/2, middle is 5/4*Pi
1323  for (unsigned int i=0; i<2; i++)
1324  for (unsigned int j=1; j<4; j++)
1325  {
1326  if (std::abs(p[0](i)-p[j](i))> numbers::PI)
1327  {
1328  middle(i)+=2*numbers::PI;
1329  }
1330  }
1331 
1332  for (unsigned int i=0; i<4; i++)
1333  middle+=p[i];
1334 
1335  middle*= 0.25;
1336 
1337  return get_real_coord(middle);
1338 }
1339 
1340 
1341 
1342 //Normal field without unit length
1343 template <>
1344 Point<3>
1346 {
1347 
1348  Point<3> n;
1349  double theta=surfP[0];
1350  double phi=surfP[1];
1351 
1352  double f=R+r*std::cos(phi);
1353 
1354  n[0]=r*std::cos(phi)*std::cos(theta)*f;
1355  n[1]=r*std::sin(phi)*f;
1356  n[2]=r*std::sin(theta)*std::cos(phi)*f;
1357 
1358  return n;
1359 }
1360 
1361 
1362 
1363 //Normal field without unit length
1364 template <>
1365 Point<3>
1367 {
1368 
1369  Point<2> surfP=get_surf_coord(p);
1370  return get_surf_norm_from_sp(surfP);
1371 
1372 }
1373 
1374 
1375 
1376 template<>
1377 void
1379 get_intermediate_points_on_line (const Triangulation<2, 3>::line_iterator &line,
1380  std::vector< Point< 3 > > &points) const
1381 {
1382  //Almost the same implementation as StraightBoundary<2,3>
1383  unsigned int npoints=points.size();
1384  if (npoints==0) return;
1385 
1386  Point<2> p[2];
1387 
1388  for (unsigned int i=0; i<2; i++)
1389  p[i]=get_surf_coord(line->vertex(i));
1390 
1391  unsigned int offset[2];
1392  offset[0]=0;
1393  offset[1]=0;
1394 
1395  //Take care for periodic conditions & negative angles, see
1396  //get_new_point_on_line() above. Because we dont have a symmetric
1397  //interpolation (just the middle) we need to add 2*Pi to each almost zero
1398  //and negative angles.
1399  for (unsigned int i=0; i<2; i++)
1400  for (unsigned int j=1; j<2; j++)
1401  {
1402  if (std::abs(p[0](i)-p[j](i))> numbers::PI)
1403  {
1404  offset[i]++;
1405  break;
1406  }
1407  }
1408 
1409  for (unsigned int i=0; i<2; i++)
1410  for (unsigned int j=0; j<2; j++)
1411  if (p[j](i)<1.E-12 ) //Take care for periodic conditions & negative angles
1412  p[j](i)+=2*numbers::PI*offset[i];
1413 
1414 
1415  Point<2> target;
1416  const std::vector<Point<1> > &line_points = this->get_line_support_points(npoints);
1417  for (unsigned int i=0; i<npoints; i++)
1418  {
1419  const double x = line_points[i+1][0];
1420  target= (1-x)*p[0] + x*p[1];
1421  points[i]=get_real_coord(target);
1422  }
1423 }
1424 
1425 
1426 
1427 template<>
1428 void
1430 get_intermediate_points_on_quad (const Triangulation< 2, 3 >::quad_iterator &quad,
1431  std::vector< Point< 3 > > &points )const
1432 {
1433  //Almost the same implementation as StraightBoundary<2,3>
1434  const unsigned int n=points.size(),
1435  m=static_cast<unsigned int>(std::sqrt(static_cast<double>(n)));
1436  // is n a square number
1437  Assert(m*m==n, ExcInternalError());
1438 
1439  Point<2> p[4];
1440 
1441  for (unsigned int i=0; i<4; i++)
1442  p[i]=get_surf_coord(quad->vertex(i));
1443 
1444  Point<2> target;
1445  unsigned int offset[2];
1446  offset[0]=0;
1447  offset[1]=0;
1448 
1449  //Take care for periodic conditions & negative angles, see
1450  //get_new_point_on_line() above. Because we dont have a symmetric
1451  //interpolation (just the middle) we need to add 2*Pi to each almost zero
1452  //and negative angles.
1453  for (unsigned int i=0; i<2; i++)
1454  for (unsigned int j=1; j<4; j++)
1455  {
1456  if (std::abs(p[0](i)-p[j](i))> numbers::PI)
1457  {
1458  offset[i]++;
1459  break;
1460  }
1461  }
1462 
1463  for (unsigned int i=0; i<2; i++)
1464  for (unsigned int j=0; j<4; j++)
1465  if (p[j](i)<1.E-12 ) //Take care for periodic conditions & negative angles
1466  p[j](i)+=2*numbers::PI*offset[i];
1467 
1468  const std::vector<Point<1> > &line_points = this->get_line_support_points(m);
1469  for (unsigned int i=0; i<m; ++i)
1470  {
1471  const double y=line_points[i+1][0];
1472  for (unsigned int j=0; j<m; ++j)
1473  {
1474  const double x=line_points[j+1][0];
1475  target=((1-x) * p[0] +
1476  x * p[1]) * (1-y) +
1477  ((1-x) * p[2] +
1478  x * p[3]) * y;
1479 
1480  points[i*m+j]=get_real_coord(target);
1481  }
1482  }
1483 }
1484 
1485 
1486 
1487 template<>
1488 void
1491  Boundary<2,3>::FaceVertexNormals &face_vertex_normals) const
1492 {
1493  for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_face; i++)
1494  face_vertex_normals[i]=get_surf_norm(face->vertex(i));
1495 }
1496 
1497 
1498 
1499 // explicit instantiations
1500 #include "tria_boundary_lib.inst"
1501 
1502 DEAL_II_NAMESPACE_CLOSE
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
void get_intermediate_points_between_points(const Point< spacedim > &p0, const Point< spacedim > &p1, std::vector< Point< spacedim > > &points) const
void get_intermediate_points_between_points(const Point< dim > &p0, const Point< dim > &p1, std::vector< Point< dim > > &points) const
virtual Point< dim > get_new_point_on_line(const typename Triangulation< dim >::line_iterator &line) const
SymmetricTensor< 2, dim, Number > e(const Tensor< 2, dim, Number > &F)
virtual void get_normals_at_vertices(const typename Triangulation< dim >::face_iterator &face, typename Boundary< dim >::FaceVertexNormals &face_vertex_normals) const
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
const double R
virtual void get_intermediate_points_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line, std::vector< Point< spacedim > > &points) const
virtual Point< dim > get_new_point_on_quad(const typename Triangulation< dim >::quad_iterator &quad) const
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:991
virtual void get_intermediate_points_on_line(const typename Triangulation< dim >::line_iterator &line, std::vector< Point< dim > > &points) const
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
Definition: point.h:89
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Boundary< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const
double get_radius(const Point< dim > x) const
Point< dim > get_surf_coord(const Point< spacedim > &p) const
double get_correct_angle(const double angle, const double x, const double y) const
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
virtual Point< spacedim > get_new_point_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line) const
virtual void get_intermediate_points_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line, std::vector< Point< spacedim > > &points) const
virtual Point< dim > get_new_point_on_line(const typename Triangulation< dim >::line_iterator &line) const
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
virtual Point< dim > get_new_point_on_line(const typename Triangulation< dim >::line_iterator &line) const
static Point< spacedim > get_axis_vector(const unsigned int axis)
static const double PI
Definition: numbers.h:94
HalfHyperShellBoundary(const Point< dim > &center=Point< dim >(), const double inner_radius=-1, const double outer_radius=-1)
Definition: tria.h:52
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual Point< spacedim > get_new_point_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad, std::vector< Point< spacedim > > &points) const
static ::ExceptionBase & ExcImpossibleInDim(int arg1)
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Boundary< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const
virtual void get_intermediate_points_on_line(const typename Triangulation< dim >::line_iterator &line, std::vector< Point< dim > > &points) const
virtual Point< dim > get_new_point_on_quad(const typename Triangulation< dim >::quad_iterator &quad) const
HalfHyperBallBoundary(const Point< dim > p=Point< dim >(), const double radius=1.0)
#define Assert(cond, exc)
Definition: exceptions.h:313
Point< spacedim > get_surf_norm(const Point< spacedim > &p) const
Point< spacedim > get_real_coord(const Point< dim > &surfP) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad, std::vector< Point< spacedim > > &points) const
ConeBoundary(const double radius_0, const double radius_1, const Point< dim > x_0, const Point< dim > x_1)
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim >::quad_iterator &quad, std::vector< Point< dim > > &points) const
virtual Point< dim > get_new_point_on_quad(const typename Triangulation< dim >::quad_iterator &quad) const
virtual void get_normals_at_vertices(const typename Triangulation< dim >::face_iterator &face, typename Boundary< dim >::FaceVertexNormals &face_vertex_normals) const
virtual void get_intermediate_points_on_line(const typename Triangulation< dim >::line_iterator &line, std::vector< Point< dim > > &points) const
double get_radius() const
HyperShellBoundary(const Point< dim > &center=Point< dim >())
Point< spacedim > get_surf_norm_from_sp(const Point< dim > &surfP) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad, std::vector< Point< spacedim > > &points) const
numbers::NumberTraits< Number >::real_type square() const
double get_radius() const
void get_intermediate_points_between_points(const Point< spacedim > &p0, const Point< spacedim > &p1, std::vector< Point< spacedim > > &points) const
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Boundary< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim, spacedim >::quad_iterator &quad, std::vector< Point< spacedim > > &points) const
TorusBoundary(const double R, const double r)
static ::ExceptionBase & ExcNotImplemented()
virtual void get_intermediate_points_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line, std::vector< Point< spacedim > > &points) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim >::quad_iterator &quad, std::vector< Point< dim > > &points) const
virtual void get_intermediate_points_on_quad(const typename Triangulation< dim >::quad_iterator &quad, std::vector< Point< dim > > &points) const
HyperBallBoundary(const Point< spacedim > p=Point< spacedim >(), const double radius=1.0)
CylinderBoundary(const double radius=1.0, const unsigned int axis=0)
virtual Tensor< 1, spacedim > normal_vector(const typename Triangulation< dim, spacedim >::face_iterator &face, const Point< spacedim > &p) const
virtual void get_normals_at_vertices(const typename Triangulation< dim, spacedim >::face_iterator &face, typename Boundary< dim, spacedim >::FaceVertexNormals &face_vertex_normals) const
Point< spacedim > get_center() const
virtual void get_intermediate_points_on_line(const typename Triangulation< dim, spacedim >::line_iterator &line, std::vector< Point< spacedim > > &points) const
static ::ExceptionBase & ExcInternalError()
virtual void get_normals_at_vertices(const typename Triangulation< dim >::face_iterator &face, typename Boundary< dim >::FaceVertexNormals &face_vertex_normals) const