Reference documentation for deal.II version 8.4.2
manifold_lib.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2013 - 2015 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.h>
17 #include <deal.II/grid/tria_iterator.h>
18 #include <deal.II/grid/tria_accessor.h>
19 #include <deal.II/grid/manifold_lib.h>
20 #include <deal.II/base/tensor.h>
21 #include <deal.II/lac/vector.h>
22 #include <cmath>
23 
24 DEAL_II_NAMESPACE_OPEN
25 
26 template <int dim, int spacedim>
28  ChartManifold<dim,spacedim,spacedim>(SphericalManifold<dim,spacedim>::get_periodicity()),
29  center(center)
30 {}
31 
32 
33 
34 template <int dim, int spacedim>
37 {
38  Point<spacedim> periodicity;
39  periodicity[spacedim-1] = 2*numbers::PI; // theta and phi period.
40  return periodicity;
41 }
42 
43 
44 template <int dim, int spacedim>
47 {
48  if (spacedim == 2)
50  else
51  {
52  double rho_average = 0;
53  Point<spacedim> mid_point;
54  for (unsigned int i=0; i<quad.size(); ++i)
55  {
56  rho_average += quad.weight(i)*(quad.point(i)-center).norm();
57  mid_point += quad.weight(i)*quad.point(i);
58  }
59  // Project the mid_point back to the right location
60  Tensor<1,spacedim> R = mid_point-center;
61  // Scale it to have radius rho_average
62  R *= rho_average/R.norm();
63  // And return it.
64  return center+R;
65  }
66 }
67 
68 
69 
70 template <int dim, int spacedim>
73 {
74  Assert(spherical_point[0] >=0.0,
75  ExcMessage("Negative radius for given point."));
76  const double rho = spherical_point[0];
77  const double theta = spherical_point[1];
78 
80  if (rho > 1e-10)
81  switch (spacedim)
82  {
83  case 2:
84  p[0] = rho*cos(theta);
85  p[1] = rho*sin(theta);
86  break;
87  case 3:
88  {
89  const double &phi= spherical_point[2];
90  p[0] = rho*sin(theta)*cos(phi);
91  p[1] = rho*sin(theta)*sin(phi);
92  p[2] = rho*cos(theta);
93  }
94  break;
95  default:
96  Assert(false, ExcInternalError());
97  }
98  return p+center;
99 }
100 
101 template <int dim, int spacedim>
104 {
105  const Tensor<1,spacedim> R = space_point-center;
106  const double rho = R.norm();
107 
108  Point<spacedim> p;
109  p[0] = rho;
110 
111  switch (spacedim)
112  {
113  case 2:
114  p[1] = atan2(R[1],R[0]);
115  if (p[1] < 0)
116  p[1] += 2*numbers::PI;
117  break;
118  case 3:
119  {
120  const double z = R[2];
121  p[2] = atan2(R[1],R[0]); // phi
122  if (p[2] < 0)
123  p[2] += 2*numbers::PI; // phi is periodic
124  p[1] = atan2(sqrt(R[0]*R[0]+R[1]*R[1]),z); // theta
125  }
126  break;
127  default:
128  Assert(false, ExcInternalError());
129  }
130  return p;
131 }
132 
133 
134 // ============================================================
135 // CylindricalManifold
136 // ============================================================
137 
138 template <int dim, int spacedim>
140  const double tolerance) :
141  direction (Point<spacedim>::unit_vector(axis)),
142  point_on_axis (Point<spacedim>()),
143  tolerance(tolerance)
144 {
145  Assert(spacedim > 1, ExcImpossibleInDim(1));
146 }
147 
148 
149 template <int dim, int spacedim>
152  const double tolerance) :
153  direction (direction),
154  point_on_axis (point_on_axis),
155  tolerance(tolerance)
156 {
157  Assert(spacedim > 2, ExcImpossibleInDim(spacedim));
158 }
159 
160 
161 
162 
163 template <int dim, int spacedim>
167 {
168  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
169  const std::vector<double> &weights = quad.get_weights();
170 
171  // compute a proposed new point
172  Point<spacedim> middle = flat_manifold.get_new_point(quad);
173 
174  double radius = 0;
175  Tensor<1,spacedim> on_plane;
176 
177  for (unsigned int i=0; i<surrounding_points.size(); ++i)
178  {
179  on_plane = surrounding_points[i]-point_on_axis;
180  on_plane = on_plane - (on_plane*direction) * direction;
181  radius += weights[i]*on_plane.norm();
182  }
183 
184  // we then have to project this point out to the given radius from
185  // the axis. to this end, we have to take into account the offset
186  // point_on_axis and the direction of the axis
187  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
188  ((middle-point_on_axis) * direction) * direction;
189 
190  // scale it to the desired length and put everything back together,
191  // unless we have a point on the axis
192  if (vector_from_axis.norm() <= tolerance * middle.norm())
193  return middle;
194 
195  else
196  return Point<spacedim>((vector_from_axis / vector_from_axis.norm() * radius +
197  ((middle-point_on_axis) * direction) * direction +
198  point_on_axis));
199 }
200 
201 
202 // ============================================================
203 // FunctionChartManifold
204 // ============================================================
205 template <int dim, int spacedim, int chartdim>
207 (const Function<chartdim> &push_forward_function,
208  const Function<spacedim> &pull_back_function,
209  const Point<chartdim> periodicity,
210  const double tolerance):
212  push_forward_function(&push_forward_function),
213  pull_back_function(&pull_back_function),
214  tolerance(tolerance),
215  owns_pointers(false)
216 {
217  AssertDimension(push_forward_function.n_components, spacedim);
218  AssertDimension(pull_back_function.n_components, chartdim);
219 }
220 
221 template <int dim, int spacedim, int chartdim>
223 (const std::string push_forward_expression,
224  const std::string pull_back_expression,
225  const Point<chartdim> periodicity,
226  const typename FunctionParser<spacedim>::ConstMap const_map,
227  const std::string chart_vars,
228  const std::string space_vars,
229  const double tolerance) :
231  const_map(const_map),
232  tolerance(tolerance),
233  owns_pointers(true)
234 {
237  pf->initialize(chart_vars, push_forward_expression, const_map);
238  pb->initialize(space_vars, pull_back_expression, const_map);
239  push_forward_function = pf;
240  pull_back_function = pb;
241 }
242 
243 template <int dim, int spacedim, int chartdim>
245 {
246  if (owns_pointers == true)
247  {
248  const Function<chartdim> *pf = push_forward_function;
249  push_forward_function = 0;
250  delete pf;
251 
252  const Function<spacedim> *pb = pull_back_function;
253  pull_back_function = 0;
254  delete pb;
255  }
256 }
257 
258 template <int dim, int spacedim, int chartdim>
261 {
262  Vector<double> pf(spacedim);
263  Point<spacedim> result;
264  push_forward_function->vector_value(chart_point, pf);
265  for (unsigned int i=0; i<spacedim; ++i)
266  result[i] = pf[i];
267 
268 #ifdef DEBUG
269  Vector<double> pb(chartdim);
270  pull_back_function->vector_value(result, pb);
271  for (unsigned int i=0; i<chartdim; ++i)
272  Assert((chart_point.norm() > tolerance &&
273  (std::abs(pb[i]-chart_point[i]) < tolerance*chart_point.norm())) ||
274  (std::abs(pb[i]-chart_point[i]) < tolerance),
275  ExcMessage("The push forward is not the inverse of the pull back! Bailing out."));
276 #endif
277 
278  return result;
279 }
280 
281 
282 template <int dim, int spacedim, int chartdim>
285 {
286  Vector<double> pb(chartdim);
287  Point<chartdim> result;
288  pull_back_function->vector_value(space_point, pb);
289  for (unsigned int i=0; i<chartdim; ++i)
290  result[i] = pb[i];
291  return result;
292 }
293 
294 // explicit instantiations
295 #include "manifold_lib.inst"
296 
297 DEAL_II_NAMESPACE_CLOSE
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1052
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const
FunctionManifold(const Function< chartdim > &push_forward_function, const Function< spacedim > &pull_back_function, const Point< chartdim > periodicity=Point< chartdim >(), const double tolerance=1e-10)
const std::vector< Point< dim > > & get_points() const
const std::vector< double > & get_weights() const
virtual Point< spacedim > pull_back(const Point< spacedim > &space_point) const
const Point< spacedim > point_on_axis
Definition: manifold_lib.h:166
::ExceptionBase & ExcMessage(std::string arg1)
const Point< dim > & point(const unsigned int i) const
numbers::NumberTraits< Number >::real_type norm() const
Definition: tensor.h:1047
const unsigned int n_components
Definition: function.h:144
static const double PI
Definition: numbers.h:74
CylindricalManifold(const unsigned int axis=0, const double tolerance=1e-10)
#define Assert(cond, exc)
Definition: exceptions.h:294
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const
Definition: manifold.cc:294
const Point< spacedim > direction
Definition: manifold_lib.h:161
virtual Point< chartdim > pull_back(const Point< spacedim > &space_point) const
unsigned int size() const
virtual Point< spacedim > push_forward(const Point< spacedim > &chart_point) const
Definition: manifold_lib.cc:72
const Point< spacedim > center
Definition: manifold_lib.h:100
virtual Point< spacedim > push_forward(const Point< chartdim > &chart_point) const
virtual Point< spacedim > get_new_point(const Quadrature< spacedim > &quad) const
Definition: manifold_lib.cc:46
void initialize(const std::string &vars, const std::vector< std::string > &expressions, const ConstMap &constants, const bool time_dependent=false)
static Point< spacedim > get_periodicity()
Definition: manifold_lib.cc:36
FlatManifold< dim, spacedim > flat_manifold
Definition: manifold_lib.h:172
SphericalManifold(const Point< spacedim > center=Point< spacedim >())
Definition: manifold_lib.cc:27
virtual void vector_value(const Point< dim > &p, Vector< Number > &values) const
double weight(const unsigned int i) const