MADNESS  0.10.1
sdf_domainmask.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: sdf_shape.h 1792 2010-01-26 12:58:18Z rjharrison $
32 */
33 
34 /*!
35  \file mra/sdf_domainmask.h
36  \brief Defines abstract interfaces and concrete classes signed distance
37  functions and domain masks.
38 
39  Interfaces for a signed distance function (sdf) and a domain mask are
40  made. The original conception of these interfaces was for doing
41  shapes and interior boundary conditions in MADNESS; however, the
42  interfaces were abstracted for other applications.
43 
44  The domain mask builds on a sdf such that \f$0 <= \mbox{mask(sdf)} <= 1\f$
45  for smooth switching between domains. That said, a mask needs a sdf.
46 
47  A general-purpose functor is given that combines a sdf and mask
48  to produce MADNESS functions for various entities including
49  - The domain mask (trace is the volume)
50  - The gradient of mask (related to the surface)
51  - The surface (trace is the surface area)
52  - The normal derivative of the surface
53 
54  \ingroup mrabcint
55 */
56 
57 #ifndef MADNESS_MRA_SDF_DOMAINMASK_H__INCLUDED
58 #define MADNESS_MRA_SDF_DOMAINMASK_H__INCLUDED
59 
60 #include <madness/mra/mra.h>
61 
62 namespace madness {
63 
64  /** \brief The interface for a signed distance function (sdf).
65 
66  A class implementing this interface will need to provide the sdf
67  given a point in coordinate space, and also the gradient of the
68  sdf at this point.
69 
70  \c NDIM is the dimensionality of the coordinate space.
71 
72  \ingroup mrabcint */
73  template <std::size_t NDIM>
75  public:
76  /** \brief Returns the signed distance from the surface,
77  - Positive is ``inside''
78  - Negative is ``outside''
79 
80  \param[in] x The coordinate
81  \return The signed distance */
82  virtual double sdf(const Vector<double,NDIM>& x) const = 0;
83 
84  /** \brief Returns the gradient of the signed distance from the
85  surface (i.e., \c dsdf(x)/dx[i] )
86 
87  \param[in] x The coordinate
88  \return The gradient */
90  const = 0;
91 
92  virtual ~SignedDFInterface() {}
93  };
94 
95  /** \brief The interface for masking functions defined by signed distance
96  functions.
97 
98  This interface was initially conceived for using shapes in MADNESS
99  to specify internal boundary conditions. The signed distance function
100  defines the shape, and this mask allows calculations of volumes,
101  surfaces, etc.
102 
103  \ingroup mrabcint */
105  public:
106  /** \brief Returns the characteristic mask function
107  - 1 in interior
108  - 0 in exterior
109  - 1/2 on boundary
110 
111  \param[in] d The signed distance from the surface
112  \return The mask or characteristic function */
113  virtual double mask(double d) const = 0;
114 
115  /** \brief Returns the derivative of the characteristic mask function
116  with respect to the distance (from the surface)
117 
118  \param[in] d The signed normal distance from the surface
119  \return Derivative of the characteristic mask function */
120  virtual double dmask(double d) const = 0;
121 
122  /** \brief Returns the value of the normalized surface layer function
123 
124  Normalized means the volume integral of this function should
125  converge to the surface area in the limit of a either an infinitely
126  thin surface or zero curvature. The function thus acts as a
127  ``delta function'' located at the boundary.
128 
129  \param[in] d The signed normal distance from the surface
130  \return Normalized surface layer function */
131  virtual double surface(double d) const = 0;
132 
133  /** \brief Returns the derivative of the normalized surface layer
134  function
135 
136  \param[in] d The signed normal distance from the surface
137  \return Derivative of the normalized surface layer function */
138  virtual double dsurface(double d) const = 0;
139 
140  virtual ~DomainMaskInterface() {}
141  };
142 
143  /** \brief Framework for combining a signed distance function (sdf)
144  with a domain mask to produce MADNESS functions.
145 
146  This interface provides functor functionality to produce MADNESS
147  functions for
148  - the domain mask (given the sdf)
149  - the derivative of the domain mask
150  - the surface (given the sdf)
151  - the normal derivative of the surface layer
152 
153  The functor defaults to the domain mask; however, member functions
154  can toggle between the other options.
155 
156  \ingroup mrabcint */
157  template <std::size_t NDIM>
158  class DomainMaskSDFFunctor : public FunctionFunctorInterface<double,NDIM> {
159 
160  private:
161  /// \brief Bury the default constructor
163 
164  private: // protected may be better if this becomes highly inherited
165  /// The domain mask to use
166  std::shared_ptr<DomainMaskInterface> mask;
167 
168  /// The signed distance function
169  std::shared_ptr<SignedDFInterface<NDIM> > sdf;
170 
171  int mswitch; ///< Which masking function to use (mask, surface, etc.)
172 
173  public:
174  // switch values
175  static const int MASK; ///< Use the \c mask() function in \c mask
176  static const int MASK_COMPLEMENT; ///< Get the complement of \c mask()
177  static const int DMASK; ///< Use the \c dmask() function in \c mask
178  static const int SURFACE; ///< Use the \c surface() function in \c mask
179  static const int DSURFACE; ///< Use the \c dsurface() function in \c mask
180 
181  /** \brief Constructor for mask/sdf functor
182 
183  \param mask Pointer to the domain mask
184  \param sdf Pointer to the signed distance function */
185  DomainMaskSDFFunctor(std::shared_ptr<DomainMaskInterface> mask,
186  std::shared_ptr<SignedDFInterface<NDIM> > sdf)
187  : mask(mask), sdf(sdf), mswitch(MASK)
188  {}
189 
190  /** \brief Constructor for mask/sdf function specifying the desired
191  function (mask, surface, etc.)
192 
193  \param mask Pointer to the domain mask
194  \param sdf Pointer to the signed distance function
195  \param[in] _mswitch Which function to use (MASK, DMASK, SURFACE,
196  DSURFACE, or MASK_COMPLEMENT) */
197  DomainMaskSDFFunctor(std::shared_ptr<DomainMaskInterface> mask,
198  std::shared_ptr<SignedDFInterface<NDIM> > sdf, int _mswitch)
199  : mask(mask), sdf(sdf), mswitch(MASK) {
200  if(_mswitch == MASK || _mswitch == DMASK || _mswitch == SURFACE ||
201  _mswitch == DSURFACE || _mswitch == MASK_COMPLEMENT) {
202  mswitch = _mswitch;
203  }
204  else {
205  error("Unrecognized function option in DomainMaskSDFFunctor" \
206  "::DomainMaskSDFFunctor()");
207  }
208  }
209 
210  /** \brief Uses the functor interface to make a MADNESS function
211 
212  \param x Point to compute value
213  \return Value of the desired function */
214  double operator()(const Vector<double,NDIM>& x) const {
216  return mask->mask(sdf->sdf(x));
218  return 1.0 - mask->mask(sdf->sdf(x));
220  return mask->dmask(sdf->sdf(x));
222  return mask->surface(sdf->sdf(x));
224  return mask->dsurface(sdf->sdf(x));
225  else {
226  error("Unknown function from DomainMaskInterface in " \
227  "DomainMaskSDFFunctor::operator()");
228  return 0.0;
229  }
230  }
231 
232  /** \brief Toggles which function from DomainMaskInterface to use when
233  making the MADNESS function.
234 
235  \param _mswitch The function to use (should be MASK, DMASK,
236  SURFACE, DSURFACE, or MASK_COMPLEMENT) */
237  void setMaskFunction(int _mswitch) {
238  if(_mswitch == MASK || _mswitch == DMASK || _mswitch == SURFACE ||
239  _mswitch == DSURFACE || _mswitch == MASK_COMPLEMENT) {
240  mswitch = _mswitch;
241  }
242  else {
243  error("Unrecognized function option in DomainMaskSDFFunctor" \
244  "::setMaskFunction()");
245  }
246  }
247 
249  };
250 
251  template<std::size_t NDIM>
252  const int DomainMaskSDFFunctor<NDIM>::MASK = 1;
253 
254  template<std::size_t NDIM>
256 
257  template<std::size_t NDIM>
258  const int DomainMaskSDFFunctor<NDIM>::DMASK = 3;
259 
260  template<std::size_t NDIM>
262 
263  template<std::size_t NDIM>
265 
266  /** \brief Provides the Li-Lowengrub-Ratz-Voight (LLRV) domain mask
267  characteristic functions.
268 
269  \ingroup mrabcint
270 
271  See X. Li, J. Lowengrub, A. R&auml;tz, and A. Voight, ``Solving PDEs in
272  Complex Geometries: A Diffuse Domain Approach,'' Commun. Math. Sci., 7,
273  p81-107, 2009.
274 
275  Given a signed distance, this class implements in the domain mask
276  and surface functions from the above reference. For the domain mask,
277 
278  \f[ \varphi(d) = \frac{1}{2}\left( 1 - \tanh\left(
279  \frac{3d}{\varepsilon} \right) \right) \f]
280 
281  where \f$d\f$ is the signed distance. The normalized surface function
282  is
283 
284  \f[ B(\varphi) = \frac{36}{\varepsilon} \varphi^2 (1-\varphi)^2. \f]
285 
286  The constant \f$36/\varepsilon\f$ is chosen to fulfill
287 
288  \f[ \int_{-\infty}^\infty B(s) \, ds = 1 \f]
289 
290  This class assumes the domain mask is uniformly 0 or 1 outside
291  signed distances \f$ |8 \epsilon| \f$ since the switching function
292  becomes 0/1 to machine precision at these levels. Specifically,
293  for this function the parameter \f$ \epsilon \f$ is an effective
294  measure of the full width of the surface layer since
295 
296  \f[ \int_{-\epsilon/2}^{\epsilon/2} B(s) \, ds \doteq 0.987 \f]
297 
298  and
299 
300  \f[ \int_{-\epsilon}^{\epsilon} B(s) \, ds \doteq 0.999963 \f] */
302  private:
303  LLRVDomainMask() : epsilon(0.0) {} ///< Forbidden
304 
305  protected:
306  const double epsilon; ///< The width of the transition region
307 
308  public:
309  /** \brief Constructor for the domain mask
310 
311  \param[in] epsilon The effective width of the surface */
313  : epsilon(epsilon)
314  {}
315 
316  /** \brief Value of characteristic function at normal distance d from
317  the surface
318 
319  \param[in] d The signed distance. Negative is ``inside,''
320  positive is ``outside.''
321  \return The domain mask */
322  double mask(double d) const {
323  if (d > 8.0*epsilon) {
324  return 0.0; // we're safely outside
325  }
326  else if (d < -8.0*epsilon) {
327  return 1.0; // inside
328  }
329  else {
330  return 0.5 * (1.0 - tanh(3.0 * d / epsilon));
331  }
332  }
333 
334  /** \brief Derivative of characteristic function with respect to the
335  normal distance
336 
337  \param[in] d The signed distance
338  \return The derivative */
339  double dmask(double d) const {
340  if (fabs(d) > 8.0*epsilon) {
341  return 0.0; // we're safely outside or inside
342  }
343  else {
344  double tanh3d = tanh(3.0*d/epsilon);
345  return 1.5*(tanh3d*tanh3d - 1.0) / epsilon;
346  }
347  }
348 
349  /** \brief Value of surface function at distance d normal to surface
350 
351  \param[in] d The signed distance
352  \return The value of the surface function */
353  double surface(double d) const {
354  double phi = mask(d);
355  double phic = 1.0 - phi;
356  return 36.0*phi*phi*phic*phic/epsilon;
357  }
358 
359  /** \brief Value of d(surface)/ddistance
360 
361  \param[in] d The signed distance
362  \return The derivative of the surface function */
363  double dsurface(double d) const {
364  double phi = mask(d);
365  double dphi = dmask(d);
366  return 72.0*phi*(1.0-phi)*dphi*(1.0 - 2.0*phi)/epsilon;
367  }
368 
369  virtual ~LLRVDomainMask() {}
370  };
371 
372  /** \brief Use a Gaussian for the surface function and the corresponding erf
373  for the domain mask. */
375  private:
376  GaussianDomainMask() : epsilon(0.0) {} ///< Forbidden
377 
378  protected:
379  const double epsilon; ///< The width of the transition region
380 
381  public:
382  /** \brief Constructor for the domain mask
383 
384  \param[in] epsilon The effective width of the surface */
386  : epsilon(epsilon)
387  {}
388 
389  /** \brief Value of characteristic function at normal distance d from
390  the surface
391 
392  \param[in] d The signed distance. Negative is ``inside,''
393  positive is ``outside.''
394  \return The domain mask */
395  double mask(double d) const {
396  if (d > 8.0*epsilon) {
397  return 0.0; // we're safely outside
398  }
399  else if (d < -8.0*epsilon) {
400  return 1.0; // inside
401  }
402  else {
403  return (1.0 - erf(d / (sqrt(2.0) * epsilon))) * 0.5;
404  }
405  }
406 
407  /** \brief Derivative of characteristic function with respect to the
408  normal distance
409 
410  \param[in] d The signed distance
411  \return The derivative */
412  double dmask(double d) const {
413  if (fabs(d) > 8.0*epsilon) {
414  return 0.0; // we're safely outside or inside
415  }
416  else {
417  return -exp(-d*d*0.5/(epsilon*epsilon)) / (sqrt(2.0*constants::pi)
418  * epsilon);
419  }
420  }
421 
422  /** \brief Value of surface function at distance d normal to surface
423 
424  \param[in] d The signed distance
425  \return The value of the surface function */
426  double surface(double d) const {
427  return exp(-d*d*0.5/(epsilon*epsilon)) / (sqrt(2.0*constants::pi)
428  * epsilon);
429  }
430 
431  /** \brief Value of d(surface)/ddistance
432 
433  \param[in] d The signed distance
434  \return The derivative of the surface function */
435  double dsurface(double d) const {
436  return -exp(-d*d*0.5/(epsilon*epsilon)) * d / (sqrt(2.0*constants::pi)
438  }
439 
440  virtual ~GaussianDomainMask() {}
441  };
442 
443 } // end of madness namespace
444 
445 #endif // MADNESS_MRA_SDF_DOMAINMASK_H__INCLUDED
The interface for masking functions defined by signed distance functions.
Definition: sdf_domainmask.h:104
virtual double dmask(double d) const =0
Returns the derivative of the characteristic mask function with respect to the distance (from the sur...
virtual double dsurface(double d) const =0
Returns the derivative of the normalized surface layer function.
virtual double mask(double d) const =0
Returns the characteristic mask function.
virtual ~DomainMaskInterface()
Definition: sdf_domainmask.h:140
virtual double surface(double d) const =0
Returns the value of the normalized surface layer function.
Framework for combining a signed distance function (sdf) with a domain mask to produce MADNESS functi...
Definition: sdf_domainmask.h:158
static const int MASK
Use the mask() function in mask.
Definition: sdf_domainmask.h:175
virtual ~DomainMaskSDFFunctor()
Definition: sdf_domainmask.h:248
DomainMaskSDFFunctor()
Bury the default constructor.
Definition: sdf_domainmask.h:162
DomainMaskSDFFunctor(std::shared_ptr< DomainMaskInterface > mask, std::shared_ptr< SignedDFInterface< NDIM > > sdf, int _mswitch)
Constructor for mask/sdf function specifying the desired function (mask, surface, etc....
Definition: sdf_domainmask.h:197
void setMaskFunction(int _mswitch)
Toggles which function from DomainMaskInterface to use when making the MADNESS function.
Definition: sdf_domainmask.h:237
double operator()(const Vector< double, NDIM > &x) const
Uses the functor interface to make a MADNESS function.
Definition: sdf_domainmask.h:214
DomainMaskSDFFunctor(std::shared_ptr< DomainMaskInterface > mask, std::shared_ptr< SignedDFInterface< NDIM > > sdf)
Constructor for mask/sdf functor.
Definition: sdf_domainmask.h:185
static const int DMASK
Use the dmask() function in mask.
Definition: sdf_domainmask.h:177
static const int MASK_COMPLEMENT
Get the complement of mask()
Definition: sdf_domainmask.h:176
std::shared_ptr< DomainMaskInterface > mask
The domain mask to use.
Definition: sdf_domainmask.h:166
std::shared_ptr< SignedDFInterface< NDIM > > sdf
The signed distance function.
Definition: sdf_domainmask.h:169
static const int SURFACE
Use the surface() function in mask.
Definition: sdf_domainmask.h:178
static const int DSURFACE
Use the dsurface() function in mask.
Definition: sdf_domainmask.h:179
int mswitch
Which masking function to use (mask, surface, etc.)
Definition: sdf_domainmask.h:171
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:68
Use a Gaussian for the surface function and the corresponding erf for the domain mask.
Definition: sdf_domainmask.h:374
double mask(double d) const
Value of characteristic function at normal distance d from the surface.
Definition: sdf_domainmask.h:395
double dsurface(double d) const
Value of d(surface)/ddistance.
Definition: sdf_domainmask.h:435
virtual ~GaussianDomainMask()
Definition: sdf_domainmask.h:440
const double epsilon
The width of the transition region.
Definition: sdf_domainmask.h:379
GaussianDomainMask(double epsilon)
Constructor for the domain mask.
Definition: sdf_domainmask.h:385
GaussianDomainMask()
Forbidden.
Definition: sdf_domainmask.h:376
double surface(double d) const
Value of surface function at distance d normal to surface.
Definition: sdf_domainmask.h:426
double dmask(double d) const
Derivative of characteristic function with respect to the normal distance.
Definition: sdf_domainmask.h:412
Provides the Li-Lowengrub-Ratz-Voight (LLRV) domain mask characteristic functions.
Definition: sdf_domainmask.h:301
double surface(double d) const
Value of surface function at distance d normal to surface.
Definition: sdf_domainmask.h:353
const double epsilon
The width of the transition region.
Definition: sdf_domainmask.h:306
virtual ~LLRVDomainMask()
Definition: sdf_domainmask.h:369
LLRVDomainMask()
Forbidden.
Definition: sdf_domainmask.h:303
double mask(double d) const
Value of characteristic function at normal distance d from the surface.
Definition: sdf_domainmask.h:322
double dmask(double d) const
Derivative of characteristic function with respect to the normal distance.
Definition: sdf_domainmask.h:339
LLRVDomainMask(double epsilon)
Constructor for the domain mask.
Definition: sdf_domainmask.h:312
double dsurface(double d) const
Value of d(surface)/ddistance.
Definition: sdf_domainmask.h:363
The interface for a signed distance function (sdf).
Definition: sdf_domainmask.h:74
virtual double sdf(const Vector< double, NDIM > &x) const =0
Returns the signed distance from the surface,.
virtual ~SignedDFInterface()
Definition: sdf_domainmask.h:92
virtual Vector< double, NDIM > grad_sdf(const Vector< double, NDIM > &x) const =0
Returns the gradient of the signed distance from the surface (i.e., dsdf(x)/dx[i] )
Main include file for MADNESS and defines Function interface.
const double pi
Mathematical constant .
Definition: constants.h:48
File holds all helper structures necessary for the CC_Operator and CC2 class.
Definition: DFParameters.h:10
void error(const char *msg)
Definition: world.cc:139
void d()
Definition: test_sig.cc:79