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
64namespace 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 {
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. */
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
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
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
static const double d
Definition nonlinschro.cc:121
Defines abstract interfaces and concrete classes signed distance functions and domain masks.
AtomicInt sum
Definition test_atomicint.cc:46
double dist(const Vector< double, 3 > v1, const Vector< double, 3 > v2)
distance between v1 and v2
Definition test_localizer.cc:38