MADNESS  0.10.1
sdf_shape_3D.h
Go to the documentation of this file.
1 /*
2  This file is part of MADNESS.
3 
4  Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20  For more information please contact:
21 
22  Robert J. Harrison
23  Oak Ridge National Laboratory
24  One Bethel Valley Road
25  P.O. Box 2008, MS-6367
26 
27  email: harrisonrj@ornl.gov
28  tel: 865-241-3937
29  fax: 865-572-0680
30 
31  $Id$
32 */
33 
34 /**
35  \file mra/sdf_shape_3D.h
36  \brief Implements the SignedDFInterface for common 3-D geometric objects.
37  \ingroup mrabcint
38 
39  This file provides signed distance functions for common 3-D geometric objects:
40  - Plane
41  - Sphere
42  - Cone
43  - Paraboloid
44  - Box
45  - Cube
46  - Ellipsoid
47  - Cylinder
48 
49  \note The signed distance functions should be the shortest distance between
50  a point and \b any point on the surface. This is hard to calculate in many
51  cases, so we use contours here. The surface layer may not be equally thick
52  around all points on the surface. Some surfaces (plane, sphere, paraboloid)
53  use the exact signed distance functions. All others use the contours, which
54  may be extremely problematic and cause excessive refinement. The sdf
55  function of the sphere class outlines how to calculate the exact signed
56  distance functions, if needed.
57 */
58 
59 #ifndef MADNESS_MRA_SDF_SHAPE_3D_H__INCLUDED
60 #define MADNESS_MRA_SDF_SHAPE_3D_H__INCLUDED
61 
63 
64 namespace madness {
65 
66  /// \brief A plane surface (3 dimensions)
67  class SDFPlane : public SignedDFInterface<3> {
68  protected:
69  const coord_3d normal; ///< The normal vector pointing OUTSIDE the surface
70  const coord_3d point; ///< A point in the plane
71 
72  public:
73 
74  /** \brief SDF for a plane transecting the entire simulation volume
75 
76  \param normal The outward normal definining the plane
77  \param point A point in the plane */
79  : normal(normal*(1.0/sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2])))
80  , point(point)
81  {}
82 
83  /** \brief Computes the normal distance
84 
85  This SDF is exact, and easy to show.
86 
87  \param pt Point at which to compute the distance from the surface
88  \return The signed distance from the surface */
89  double sdf(const coord_3d& pt) const {
90  return (pt[0]-point[0])*normal[0] + (pt[1]-point[1])*normal[1] + (pt[2]-point[2])*normal[2];
91  }
92 
93  /** \brief Computes the gradient of the SDF.
94 
95  \param pt Point at which to compute the gradient
96  \return the gradient */
97  coord_3d grad_sdf(const coord_3d& pt) const {
98  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
99  }
100  };
101 
102  /// \brief A spherical surface (3 dimensions)
103  class SDFSphere : public SignedDFInterface<3> {
104  protected:
105  const double radius; ///< Radius of sphere
106  const coord_3d center; ///< Center of sphere
107 
108  public:
109  /** \brief SDF for a sphere
110 
111  \param radius The radius of the sphere
112  \param center The center of the sphere */
113  SDFSphere(const double radius, const coord_3d &center)
114  : radius(radius)
115  , center(center)
116  {}
117 
118  /** \brief Computes the normal distance
119 
120  This SDF is exact, and easy to show.
121 
122  \param pt Point at which to compute the distance from the surface
123  \return The signed distance from the surface */
124  double sdf(const coord_3d& pt) const {
125  double temp, r;
126  int i;
127 
128  r = 0.0;
129  for(i = 0; i < 3; ++i) {
130  temp = pt[i] - center[i];
131  r += temp * temp;
132  }
133 
134  return sqrt(r) - radius;
135  }
136 
137  /** \brief Computes the gradient of the SDF.
138 
139  \param pt Point at which to compute the gradient
140  \return the gradient */
141  coord_3d grad_sdf(const coord_3d& pt) const {
142  double x = pt[0] - center[0];
143  double y = pt[1] - center[1];
144  double z = pt[2] - center[2];
145  double r = sqrt(x*x + y*y + z*z);
146  coord_3d g;
147  g[0] = x/r;
148  g[1] = y/r;
149  g[2] = z/r;
150  return g;
151  }
152  };
153 
154  /** \brief A cone (3 dimensions)
155 
156  The cone is defined by
157 
158  \f[ \sqrt{x^2 + y^2} - c * z = 0 \f]
159 
160  where \f$ z \f$ is along the cone's axis. */
161  class SDFCone : public SignedDFInterface<3> {
162  protected:
163  const coord_3d apex; ///< The apex
164  const double c; ///< The radius
165  const coord_3d dir; ///< The direction of the axis, from the apex INSIDE
166 
167  public:
168  /** \brief Constructor for cone
169 
170  \param c Parameter \f$ c \f$ in the definition of the cone
171  \param apex Apex of cone
172  \param direc Oriented axis of the cone */
173  SDFCone(const double c, const coord_3d &apex, const coord_3d &direc)
174  : apex(apex)
175  , c(c)
176  , dir(direc*(1.0/sqrt(direc[0]*direc[0] + direc[1]*direc[1] + direc[2]*direc[2])))
177  {}
178 
179  /** \brief Computes the normal distance
180 
181  This SDF naively uses contours, and should be improved before
182  serious usage.
183 
184  \param pt Point at which to compute the distance from the surface
185  \return The signed distance from the surface */
186  double sdf(const coord_3d& pt) const {
187  coord_3d diff;
188  unsigned int i;
189  double dotp;
190 
191  for(i = 0; i < 3; ++i)
192  diff[i] = pt[i] - apex[i];
193 
194  dotp = diff[0]*dir[0] + diff[1]*dir[1] + diff[2]*dir[2];
195 
196  for(i = 0; i < 3; ++i)
197  diff[i] -= dotp * dir[i];
198 
199  return sqrt(diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2])
200  - c * dotp;
201  }
202 
203  /** \brief Computes the gradient of the SDF.
204 
205  \param pt Point at which to compute the gradient
206  \return the gradient */
207  coord_3d grad_sdf(const coord_3d& pt) const {
208  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
209  }
210  };
211 
212  /** \brief A paraboloid (3 dimensions)
213 
214  The surface is defined by
215 
216  \f[ x^2 + y^2 - c * z == 0 \f]
217 
218  where \f$ z \f$ is along the paraboloid's axis. */
219  class SDFParaboloid : public SignedDFInterface<3> {
220  protected:
221  const coord_3d apex; ///< The apex
222  const double c; ///< Curvature/radius of the surface
223  const coord_3d dir;///< The direction of the axis, from the apex INSIDE
224  const long double zero; ///< Numerical zero for root-finding in sdf
225  const long double rootzero; ///< Numerical zero for the roots
226 
227  public:
228  /** \brief Constructor for paraboloid
229 
230  \param c Parameter \f$ c \f$ in the definition of the paraboloid
231  \param apex Apex of paraboloid
232  \param direc Oriented axis of the paraboloid */
233  SDFParaboloid(const double c, const coord_3d &apex, const coord_3d &direc)
234  : apex(apex)
235  , c(c)
236  , dir(direc*(1.0/sqrt(direc[0]*direc[0] + direc[1]*direc[1] + direc[2]*direc[2])))
237  , zero(1.0e-10L)
238  , rootzero(1.0e-14L)
239  {}
240 
241  /** \brief Computes the normal distance.
242 
243  This SDF is exact.
244 
245  Given a point, pt=(x, y, z), the goal is to find another point,
246  pt0=(x0, y0, z0), on the surface that minimizes |pt - pt0|^2. The
247  root of this minimized square distance (and a sign) is the sdf.
248 
249  For simplicity (here), I will assume that the paraboloid's axis
250  is along the positive z-axis and that the origin is the apex.
251  Note that the code does NOT make these assumptions.
252 
253  Thus, we want to minimize
254  (x-x0)^2 + (y-y0)^2 + (z-z0)^2
255  subject to
256  x0^2 + y0^2 - c z0 == 0.
257 
258  Using Lagrange multipliers, the system of equations is
259  -2(x-x0) == L 2 x0
260  -2(y-y0) == L 2 y0
261  -2(z-z0) == L (-c)
262  x0^2 + y0^2 - c z0 == 0.
263 
264  After some algebra, we get a cubic equation for L,
265  (x^2 + y^2 - c z) + (2c z + c^2/2) L - c (z + c) L^2
266  + c^2/2 L^3 == 0
267 
268  This can be solved analytically in Mathematica, producing a long,
269  messy equation. This equation has some stability issues (large
270  cancellations in some areas) and is not implemented below.
271  Instead we use an iterative root finder to locate the roots of the
272  cubic. The simple bisection method is used, perhaps someone will
273  improve the code someday).
274 
275  Once we have the correct Lagrange multiplier,
276  |pt - pt0|^2 = c L^2 (z - L c/2 + c/4).
277  The square root of this quantity (with the appropriate sign for
278  inside/outside) gives the sdf.
279 
280  \param pt Point at which to compute the distance from the surface
281  \return The signed distance from the surface */
282  double sdf(const coord_3d& pt) const {
283  // work in extended precision since this calculation can have
284  // large cancellations
286  unsigned int i, n;
287  long double dotp, d;
288  long double dist, temp[2], upper;
289  //double lambda;
290  std::vector<long double> roots;
291 
292  // silence warnings ... doesn't work
293  //lambda = 0.0;
294  dist = 0.0;
295 
296  // avoid lots of casting
297  long double c = (long double)this->c;
298 
299  for(i = 0; i < 3; ++i)
300  diff[i] = pt[i] - apex[i];
301 
302  dotp = diff[0]*dir[0] + diff[1]*dir[1] + diff[2]*dir[2];
303 
304  for(i = 0; i < 3; ++i)
305  diff[i] -= dotp * dir[i];
306 
307  d = diff[0]*diff[0] + diff[1]*diff[1] + diff[2]*diff[2]
308  - c * dotp;
309  //printf(" %.16Le %.16Le %.16Le\n", c, d, dotp);
310 
311  // get the real roots (Lagrange multipliers) and find the one
312  // that minimizes the distance.
313  // note that real roots must be no bigger than (4dotp+c)/(2c)
314  // from the analytical form
315  roots = get_roots(c, d, dotp);
316  upper = (4.0L*dotp + c) * 0.5L / c;
317  n = 0;
318  for(std::vector<long double>::iterator iter = roots.begin();
319  iter != roots.end(); ++iter) {
320 
321  temp[0] = *iter;
322 
323  // are we in range?
324  if(temp[0] <= upper) {
325 
326  // calculate the distance
327  temp[1] = c*(dotp - temp[0]*c*0.5L + c*0.25L);
328  if(temp[1] < 0.0L) {
329  // temp[1] is analytically non-negative
330  // if we're here, it's noise
331  temp[1] = 0.0L;
332  }
333  else {
334  temp[1] = std::abs(temp[0])*sqrt(temp[1]);
335  }
336 
337  if(n == 0) {
338  //lambda = temp[0];
339  dist = temp[1];
340  }
341  else {
342  if(temp[1] < dist) {
343  //lambda = temp[0];
344  dist = temp[1];
345  }
346  }
347  ++n;
348  }
349  }
350  //printf(" L = %.16Le D = %.16Le\n", lambda, dist);
351 
352  MADNESS_ASSERT(n > 0); // we should have at least one real root...
353 
354  if(d > 0.0L)
355  return (double)dist;
356  else
357  return (double)(-dist);
358  }
359 
360  /** \brief Computes the gradient of the SDF.
361 
362  \param pt Point at which to compute the gradient
363  \return the gradient */
364  coord_3d grad_sdf(const coord_3d& pt) const {
365  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
366  }
367 
368  protected:
369  /** \brief Finds real root(s) of the cubic polynomial in the sdf
370  function.
371 
372  The cubic equation can successfully solve the cubic analytically,
373  but evaluating the expression can be numerically irksome.
374  Analytical results show that at most one root appears in each of
375  the domains
376  - (-Infinity, (2z+2c-|c-2z|)/(3c))
377  - ((2z+2c-|c-2z|)/(3c), (2z+2c+|c-2z|)/(3c))
378  - ((2z+2c-|c-2z|)/(3c), Infinity).
379 
380  Furthermore, the cubic is always increasing in the first and
381  third domains, and always decreasing in the second.
382 
383  Since the cubic is easy to evaluate, we use simple bisections
384  to find the roots... this can probably be improved.
385 
386  Cubic equation of interest:
387  d + c(2z+c/2)*L - c(c+z)L^2 + c^2/2L^3 == 0
388 
389  \param[in] c Parameter c for the paraboloid.
390  \param[in] d The d parameter: x^2+y^2-cz = d
391  \param[in] z The distance from the apex along the paraboloid's
392  axis (called dotp in sdf)
393  \return The root(s)
394  */
395  std::vector<long double> get_roots(const long double c,
396  const long double d, const long double z) const {
397 
398  long double lower, upper, bound;
399  std::vector<long double> roots(0);
400  long double derivroot1, derivroot2, temp;
401  bool hasregion2, keepgoing, foundroot;
402 
403  // calculate the region boundaries
404  lower = 2.0L*(c+z);
405  upper = std::abs(c - 2.0L*z);
406  hasregion2 = (upper >= 1.0e-10L);
407 
408  derivroot1 = (lower - upper) / (3.0L*c);
409  derivroot2 = (lower + upper) / (3.0L*c);
410 
411  // first region -------------------------------------------------
412  foundroot = false;
413  upper = derivroot1;
414 
415  // if cubic(upper) < 0.0, there's no root in this region
416  bound = eval_cubic(upper, c, d, z);
417  if(std::abs(bound) < zero) {
418  // this is the root!
419  roots.push_back(upper);
420  hasregion2 = false;
421  }
422  if(bound > 0.0L) {
423  // there's a root in region 1: find it!
424 
425  // need to find a lower bound
426  temp = -1.0;
427  do {
428  lower = upper + temp;
429  bound = eval_cubic(lower, c, d, z);
430  if(std::abs(bound) < zero) {
431  // found the root!
432  roots.push_back(lower);
433  foundroot = true;
434  break;
435  }
436 
437  keepgoing = (bound > 0.0L);
438  // if we didn't cross the root, we have a better upperbound
439  if(keepgoing)
440  upper = lower;
441  } while(keepgoing);
442 
443  // with a lower and upper bound, find the root!
444  if(!foundroot) {
445  temp = find_root(lower, upper, c, d, z, true);
446  roots.push_back(temp);
447  }
448  }
449  else {
450  // no root in region 1; hence no root in region 2
451  hasregion2 = false;
452  }
453 
454  // second region ------------------------------------------------
455  if(hasregion2) {
456  lower = derivroot1;
457  upper = derivroot2;
458  // the lower range has to be positive the upper range has to be
459  // negative
460  if(lower > 0.0L && upper < 0.0L) {
461  temp = find_root(lower, upper, c, d, z, false);
462  roots.push_back(temp);
463  }
464  }
465 
466  // third region -------------------------------------------------
467  foundroot = false;
468  lower = derivroot2;
469 
470  // if cubic(upper) > 0.0, there's no root in this region
471  bound = eval_cubic(lower, c, d, z);
472  if(std::abs(bound) < zero) {
473  // this is the root!
474  roots.push_back(lower);
475  }
476  if(bound < 0.0L) {
477  // there's a root in region 3: find it!
478 
479  // need to find an upper bound
480  temp = 1.0;
481  do {
482  upper = lower + temp;
483  bound = eval_cubic(upper, c, d, z);
484  if(std::abs(bound) < zero) {
485  // found the root!
486  roots.push_back(upper);
487  foundroot = true;
488  break;
489  }
490 
491  keepgoing = (bound < 0.0L);
492  // if we didn't cross the root, we have a better lowerbound
493  if(keepgoing)
494  lower = upper;
495  } while(keepgoing);
496 
497  // with a lower and upper bound, find the root!
498  if(!foundroot) {
499  temp = find_root(lower, upper, c, d, z, true);
500  roots.push_back(temp);
501  }
502  }
503 
504  return roots;
505  }
506 
507  /** Finds a root in the specified range for the cubic equation.
508 
509  This uses a simple bisection method... perhaps someone will
510  improve it one day...
511 
512  \param[in] lower The bottom of the range
513  \param[in] upper The top of the range
514  \param[in] c Parameter c for the paraboloid.
515  \param[in] d The d parameter: x^2+y^2-cz = d
516  \param[in] z The distance from the apex along the paraboloid's
517  axis (called dotp in sdf)
518  \param[in] dir True if the function is increasing in the domain,
519  false for decreasing
520  \return the root.
521  */
522  long double find_root(long double lower, long double upper,
523  const long double c, const long double d,
524  const long double z, bool dir) const {
525 
526  long double value, middle;
527  do {
528  middle = 0.5L*(upper + lower);
529  value = eval_cubic(middle, c, d, z);
530 
531  if(std::abs(value) < zero)
532  return middle;
533 
534  if(value < 0.0L) {
535  if(dir)
536  lower = middle;
537  else
538  upper = middle;
539  }
540  else {
541  if(dir)
542  upper = middle;
543  else
544  lower = middle;
545  }
546  } while(std::abs(upper-lower) > rootzero);
547 
548  return middle;
549  }
550 
551  /** \brief Evaluates the cubic equation for the Lagrangian multipliers
552 
553  Cubic equation of interest:
554  d + c(2z+c/2)*L - c(c+z)L^2 + c^2/2L^3 == 0
555 
556  \param[in] x Value at which to evaluate.
557  \param[in] c Parameter c for the paraboloid.
558  \param[in] d The d parameter: x^2+y^2-cz = d
559  \param[in] z The distance from the apex along the paraboloid's
560  axis (called dotp in sdf)
561  \return the value
562  */
563  long double eval_cubic(const long double x, const long double c,
564  const long double d, const long double z)
565  const {
566  return ((c*0.5L*x - (c + z))*x + (2.0L*z + c*0.5L))*c*x + d;
567  }
568 
569  /** \brief Evaluates the derivative of the cubic equation for the
570  Lagrangian multipliers
571 
572  Cubic equation of interest:
573  d + c(2z+c/2)*L - c(c+z)L^2 + c^2/2L^3 == 0
574 
575  Derivative:
576  c(2z+c/2) - 2c(c+z)L + 3c^2/2 L^2
577 
578  \param[in] x Value at which to evaluate.
579  \param[in] c Parameter c for the paraboloid.
580  \param[in] d The d parameter: x^2+y^2-cz = d
581  \param[in] z The distance from the apex along the paraboloid's
582  axis (called dotp in sdf)
583  \return the value
584  */
585  long double eval_cubic_deriv(const long double x, const long double c,
586  const long double d, const long double z)
587  const {
588  return c*((1.5L*c*x - 2.0L*(c+z))*x + 2.0L*z + 0.5L*c);
589  }
590  };
591 
592  /** \brief A box (3 dimensions)
593 
594  \note LIMIT -- the 3 primary axes must be x, y, and z */
595  class SDFBox : public SignedDFInterface<3> {
596  protected:
597  const coord_3d lengths; ///< Half the length of each side of the box
598  const coord_3d center; ///< the center of the box
599 
600  public:
601  /** \brief Constructor for box
602 
603  \param length The lengths of the box
604  \param center The center of the box */
606  : lengths(length*0.5), center(center)
607  {}
608 
609  /** \brief Computes the normal distance
610 
611  This SDF naively uses contours, and should be improved before
612  serious usage. If far from the corners, the SDF is easy (similar
613  to a plane), and is essentially what's implemented.
614 
615  \param pt Point at which to compute the distance from the surface
616  \return The signed distance from the surface */
617  double sdf(const coord_3d& pt) const {
618  double diff, max;
619  int i;
620 
621  max = fabs(pt[0] - center[0]) - lengths[0];
622  for(i = 1; i < 3; ++i) {
623  diff = fabs(pt[i] - center[i]) - lengths[i];
624  if(diff > max)
625  max = diff;
626  }
627 
628  return max;
629  }
630 
631  /** Computes the gradient of the SDF.
632 
633  \param pt Point at which to compute the gradient
634  \return the gradient */
635  coord_3d grad_sdf(const coord_3d& pt) const {
636  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
637  }
638  };
639 
640  /** \brief A cube (3 dimensions)
641 
642  \note LIMIT -- the 3 primary axes must be x, y, and z */
643  class SDFCube : public SDFBox {
644  public:
645  /** \brief Constructor for box
646 
647  \param length The length of each side of the cube
648  \param center The center of the cube */
649  SDFCube(const double length, const coord_3d& center)
651  {}
652  };
653 
654  /** \brief An ellipsoid (3 dimensions)
655 
656  \note LIMIT -- the 3 primary axes must be x, y, and z */
657  class SDFEllipsoid : public SignedDFInterface<3> {
658  protected:
659  coord_3d radii; ///< the directional radii
660  coord_3d center; ///< the center
661 
662  public:
663  /** \brief Constructor for ellipsoid
664 
665  \param radii The directional radii of the ellipsoid
666  \param center The center of the ellipsoid */
668  : radii(radii)
669  , center(center)
670  {}
671 
672  /** \brief Computes the normal distance
673 
674  This SDF naively uses contours, and should be improved before
675  serious usage.
676 
677  \param pt Point at which to compute the distance from the surface
678  \return The signed distance from the surface */
679  double sdf(const coord_3d& pt) const {
680  double quot, sum;
681  int i;
682 
683  sum = 0.0;
684  for(i = 0; i < 3; ++i) {
685  quot = (pt[i] - center[i]) / radii[i];
686  sum += quot * quot;
687  }
688 
689  return sum - 1.0;
690  }
691 
692  /** Computes the gradient of the SDF.
693 
694  \param pt Point at which to compute the gradient
695  \return the gradient */
696  coord_3d grad_sdf(const coord_3d& pt) const {
697  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
698  }
699  };
700 
701  /// \brief A cylinder (3 dimensions)
702  class SDFCylinder : public SignedDFInterface<3> {
703  protected:
704  double radius; ///< the radius of the cylinder
705  double a; ///< half the length of the cylinder
706  coord_3d center; ///< the central axial point of the cylinder (distance a from both ends)
707  coord_3d axis; ///< the axial direction of the cylinder
708 
709  public:
710  /** \brief Constructor for cylinder
711 
712  \param radius The radius of the cylinder
713  \param length The length of the cylinder
714  \param axpt The central axial point of the cylinder (equidistant
715  from both ends)
716  \param axis The axial direction of the cylinder */
717  SDFCylinder(const double radius, const double length, const coord_3d& axpt, const coord_3d& axis)
718  : radius(radius)
719  , a(length / 2.0)
720  , center(axpt)
721  , axis(axis*(1.0/sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2])))
722  {}
723 
724  /** \brief Computes the normal distance
725 
726  This SDF naively uses contours, and should be improved before
727  serious usage.
728 
729  \param pt Point at which to compute the distance from the surface
730  \return The signed distance from the surface */
731  double sdf(const coord_3d& pt) const {
732  double dist;
733  coord_3d rel, radial;
734  int i;
735 
736  // axial distance
737  dist = 0.0;
738  for(i = 0; i < 3; ++i) {
739  rel[i] = pt[i] - center[i];
740  dist += rel[i] * axis[i];
741  }
742 
743  // get the radial component
744  for(i = 0; i < 3; ++i)
745  radial[i] = rel[i] - dist * axis[i];
746 
747  return std::max(fabs(dist) - a, sqrt(radial[0]*radial[0] + radial[1]*radial[1]
748  + radial[2]*radial[2]) - radius);
749  }
750 
751  /** Computes the gradient of the SDF.
752 
753  \param pt Point at which to compute the gradient
754  \return the gradient */
755  coord_3d grad_sdf(const coord_3d& pt) const {
756  MADNESS_EXCEPTION("gradient method is not yet implemented for this shape",0);
757  }
758  };
759 
760 } // end of madness namespace
761 
762 #endif // MADNESS_MRA_SDF_SHAPE_3D_H__INCLUDED
A box (3 dimensions)
Definition: sdf_shape_3D.h:595
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:617
coord_3d grad_sdf(const coord_3d &pt) const
Definition: sdf_shape_3D.h:635
const coord_3d lengths
Half the length of each side of the box.
Definition: sdf_shape_3D.h:597
const coord_3d center
the center of the box
Definition: sdf_shape_3D.h:598
SDFBox(const coord_3d &length, const coord_3d &center)
Constructor for box.
Definition: sdf_shape_3D.h:605
A cone (3 dimensions)
Definition: sdf_shape_3D.h:161
const coord_3d dir
The direction of the axis, from the apex INSIDE.
Definition: sdf_shape_3D.h:165
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:186
SDFCone(const double c, const coord_3d &apex, const coord_3d &direc)
Constructor for cone.
Definition: sdf_shape_3D.h:173
const coord_3d apex
The apex.
Definition: sdf_shape_3D.h:163
const double c
The radius.
Definition: sdf_shape_3D.h:164
coord_3d grad_sdf(const coord_3d &pt) const
Computes the gradient of the SDF.
Definition: sdf_shape_3D.h:207
A cube (3 dimensions)
Definition: sdf_shape_3D.h:643
SDFCube(const double length, const coord_3d &center)
Constructor for box.
Definition: sdf_shape_3D.h:649
A cylinder (3 dimensions)
Definition: sdf_shape_3D.h:702
double radius
the radius of the cylinder
Definition: sdf_shape_3D.h:704
coord_3d grad_sdf(const coord_3d &pt) const
Definition: sdf_shape_3D.h:755
coord_3d center
the central axial point of the cylinder (distance a from both ends)
Definition: sdf_shape_3D.h:706
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:731
double a
half the length of the cylinder
Definition: sdf_shape_3D.h:705
coord_3d axis
the axial direction of the cylinder
Definition: sdf_shape_3D.h:707
SDFCylinder(const double radius, const double length, const coord_3d &axpt, const coord_3d &axis)
Constructor for cylinder.
Definition: sdf_shape_3D.h:717
An ellipsoid (3 dimensions)
Definition: sdf_shape_3D.h:657
coord_3d center
the center
Definition: sdf_shape_3D.h:660
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:679
coord_3d grad_sdf(const coord_3d &pt) const
Definition: sdf_shape_3D.h:696
coord_3d radii
the directional radii
Definition: sdf_shape_3D.h:659
SDFEllipsoid(const coord_3d &radii, const coord_3d &center)
Constructor for ellipsoid.
Definition: sdf_shape_3D.h:667
A paraboloid (3 dimensions)
Definition: sdf_shape_3D.h:219
coord_3d grad_sdf(const coord_3d &pt) const
Computes the gradient of the SDF.
Definition: sdf_shape_3D.h:364
long double find_root(long double lower, long double upper, const long double c, const long double d, const long double z, bool dir) const
Definition: sdf_shape_3D.h:522
const double c
Curvature/radius of the surface.
Definition: sdf_shape_3D.h:222
const long double rootzero
Numerical zero for the roots.
Definition: sdf_shape_3D.h:225
SDFParaboloid(const double c, const coord_3d &apex, const coord_3d &direc)
Constructor for paraboloid.
Definition: sdf_shape_3D.h:233
long double eval_cubic(const long double x, const long double c, const long double d, const long double z) const
Evaluates the cubic equation for the Lagrangian multipliers.
Definition: sdf_shape_3D.h:563
const coord_3d apex
The apex.
Definition: sdf_shape_3D.h:221
std::vector< long double > get_roots(const long double c, const long double d, const long double z) const
Finds real root(s) of the cubic polynomial in the sdf function.
Definition: sdf_shape_3D.h:395
long double eval_cubic_deriv(const long double x, const long double c, const long double d, const long double z) const
Evaluates the derivative of the cubic equation for the Lagrangian multipliers.
Definition: sdf_shape_3D.h:585
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:282
const long double zero
Numerical zero for root-finding in sdf.
Definition: sdf_shape_3D.h:224
const coord_3d dir
The direction of the axis, from the apex INSIDE.
Definition: sdf_shape_3D.h:223
A plane surface (3 dimensions)
Definition: sdf_shape_3D.h:67
const coord_3d normal
The normal vector pointing OUTSIDE the surface.
Definition: sdf_shape_3D.h:69
coord_3d grad_sdf(const coord_3d &pt) const
Computes the gradient of the SDF.
Definition: sdf_shape_3D.h:97
const coord_3d point
A point in the plane.
Definition: sdf_shape_3D.h:70
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:89
SDFPlane(const coord_3d &normal, const coord_3d &point)
SDF for a plane transecting the entire simulation volume.
Definition: sdf_shape_3D.h:78
A spherical surface (3 dimensions)
Definition: sdf_shape_3D.h:103
SDFSphere(const double radius, const coord_3d &center)
SDF for a sphere.
Definition: sdf_shape_3D.h:113
const double radius
Radius of sphere.
Definition: sdf_shape_3D.h:105
const coord_3d center
Center of sphere.
Definition: sdf_shape_3D.h:106
double sdf(const coord_3d &pt) const
Computes the normal distance.
Definition: sdf_shape_3D.h:124
coord_3d grad_sdf(const coord_3d &pt) const
Computes the gradient of the SDF.
Definition: sdf_shape_3D.h:141
The interface for a signed distance function (sdf).
Definition: sdf_domainmask.h:74
@ upper
Definition: dirac-hatom.cc:15
@ lower
Definition: dirac-hatom.cc:15
static const double length
Definition: hedft.cc:48
#define max(a, b)
Definition: lda.h:51
#define MADNESS_EXCEPTION(msg, value)
Macro for throwing a MADNESS exception.
Definition: madness_exception.h:119
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition: madness_exception.h:134
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
Function< T, NDIM > sum(World &world, const std::vector< Function< T, NDIM > > &f, bool fence=true)
Returns new function — q = sum_i f[i].
Definition: vmra.h:1421
NDIM const Function< R, NDIM > & g
Definition: mra.h:2416
static long abs(long a)
Definition: tensor.h:218
static Function< T, NDIM > diff(const Function< T, NDIM > &f, int axis)
Definition: navstokes_cosines.cc:119
Defines abstract interfaces and concrete classes signed distance functions and domain masks.
double dist(const Vector< double, 3 > v1, const Vector< double, 3 > v2)
distance between v1 and v2
Definition: test_localizer.cc:38
void d()
Definition: test_sig.cc:79