weight.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra portage project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 #ifndef PORTAGE_SUPPORT_WEIGHT_H_
7 #define PORTAGE_SUPPORT_WEIGHT_H_
8 
9 #include <cmath>
10 #include <array>
11 #include <cassert>
12 #include <limits>
13 #include <vector>
14 
15 // portage includes
17 #include "wonton/support/Point.h"
18 
19 namespace Portage { namespace Meshfree { namespace Weight {
20 
21 //\///////////////////////////////////////////////////////////////////////////
22 // constants and maths functions
23 //\///////////////////////////////////////////////////////////////////////////
24 
29 double const normconst[4] = { 2./3., 1./(.7 * M_PI), 1./M_PI, 1./M_PI };
30 
35 
42 inline double sign(double x) { return x > 0. ? 1. : (x < 0. ? -1. : 0.); }
43 
45 inline double unit_step(double x) { return 0.5 * (1. + sign(x)); }
46 
47 //\///////////////////////////////////////////////////////////////////////////
48 // various scalar kernels and derivatives
49 //\///////////////////////////////////////////////////////////////////////////
50 
57 inline double b4(double x) {
58  return (std::pow(2. - std::abs(x), 3) * unit_step(2. - std::abs(x))
59  * unit_step(-1. + std::abs(x))) / 4.
60  + (1. - 1.5 * std::pow(x, 2)
61  + 0.75 * std::pow(std::abs(x), 3)) * unit_step(1. - std::abs(x));
62 }
63 
70 inline double db4(double x) {
71  return (-3. * x + (9. * std::pow(x, 2) * sign(x)) / 4.)
72  * unit_step(1. - std::abs(x)) - (3. * std::pow(2. - std::abs(x), 2)
73  * sign(x) * unit_step(2. - std::abs(x)) * unit_step(-1. + std::abs(x))) / 4.;
74 }
75 
82 inline double ddb4(double x) {
83  return (-3. + (9. * x * sign(x)) / 2.) * unit_step(1. - std::abs(x))
84  + (3. * (2. - std::abs(x)) * unit_step(2. - std::abs(x))
85  * unit_step(-1. + std::abs(x))) / 2.;
86 }
87 
94 inline double ib4(double x) {
95  return unit_step(-2. + x) + 0.6666666666666666 *
96  ((1.4375 + (0.25 - std::pow(-2. + x, 4) / 4.) / 4.) *
97  unit_step(2. - x) * unit_step(-1. + x) +
98  (0.75 + x - std::pow(x, 3) / 2. + (3. * std::pow(x, 4)) / 16.) *
99  unit_step(1. - x) * unit_step(x) +
100  (0.75 + x - std::pow(x, 3) / 2. - (3. * std::pow(x, 4)) / 16.) *
101  unit_step(-x) * unit_step(1. + x) +
102  (std::pow(2. + x, 4) * unit_step(-1. - x) * unit_step(2. + x)) / 16.);
103 }
104 
111 inline double b4lh(double x) {
112  return 0.0625 * std::pow(2. - std::abs(x), 3) * (1. + sign(-1. - x)) *
113  (1. + sign(2. + x)) +
114  0.5 * (1. - (3. * std::pow(x, 2)) / 2. + (3. * std::pow(std::abs(x), 3)) / 4.) *
115  (1. + sign(1. + x)) * unit_step(-x);
116 }
117 
124 inline double b4rh(double x) {
125  return 0.0625 * std::pow(2. - std::abs(x), 3) * (1. + sign(2. - x)) *
126  (1. + sign(-1. + x)) +
127  0.5 * (1. - (3. * std::pow(x, 2)) / 2. + (3. * std::pow(std::abs(x), 3)) / 4.) *
128  (1. + sign(1. - x)) * unit_step(x);
129 }
130 
137 inline double epanechnikov(double x) {
138  return std::abs(x) >= 2. ? 0. : 0.375 * (1. - x * x * 0.25);
139 }
140 
147 inline double depanechnikov(double x) { return std::abs(x) >= 2. ? 0. : -.1875 * x; }
148 
155 inline double ddepanechnikov(double x) { return std::abs(x) >= 2. ? 0. : -.1875; }
156 
163 inline double square(double x) { return std::abs(x) <= 2. ? 1. : 0.; }
164 
171 inline double dsquare(double x) { return 0.; }
172 
179 inline double ddsquare(double x) { return 0.; }
180 
187 inline double polyramp(double x) {
188  return (x < 0. ? 1.
189  : (((1.5 - x) * (1. + sign(1. - x))) * .5
190  + ((2. + (-2. + .5 * x) * x) * (1. + sign(2. - x))
191  * (1. + sign(-1. + x))) * .25) / 1.5); // normalize to 1 at x=0
192 }
193 
200 inline double dpolyramp(double x) {
201  return (((-1.) * (1. + sign(1. - x))) * .5 +
202  ((-2. + x) * (1. + sign(2. - x)) * (1. + sign(-1. + x))) / 4.) / 1.5;
203 }
204 
211 inline double ddpolyramp(double x) {
212  return (((0.) * (1. + sign(1. - x))) * .5 +
213  ((1.) * (1. + sign(2. - x)) * (1. + sign(-1. + x))) / 4.) / 1.5;
214 }
215 
222 inline double invsqrt(double x) {
223  double const ax = std::abs(x);
224  return 0.5 * (1. + sign(2. - ax)) * ((ax - 2.) * ax + 4.) *
225  pow(ax + epsilon, -0.5);
226 }
227 
234 inline double dinvsqrt(double x) {
235  double const sx = 1.; //x > 0 ? 1. : 1.;
236  double const ax = std::abs(x);
237  return 0.25 * (1. + sign(2. - ax)) * sx * ((3. * ax - 4.) * ax - 4.) *
238  std::pow(ax + epsilon, -1.5);
239 }
240 
247 inline double ddinvsqrt(double x) {
248  double const ax = std::abs(x);
249  return 0.125 * (1. + sign(2. - ax)) * ((3. * ax + 4.) * ax + 12.) *
250  std::pow(ax + epsilon, -2.5);
251 }
252 
259 inline double coulomb(double x) { return 1. / (std::abs(x) + epsilon); }
260 
267 inline double dcoulomb(double x) { return -sign(x) / (x * x + epsilon); }
268 
275 inline double ddcoulomb(double x) { return 2. / (x * x * std::abs(x) + epsilon); }
276 
283 inline double step(double x) { return x <= 2 ? 1. : 0.; }
284 
291 inline double dstep(double x) { return 0.; }
292 
299 inline double ddstep(double x) { return 0.; }
300 
305 
313 inline double kernel(const Kernel kern, double x) {
314  switch (kern) {
315  case B4: return b4(x);
316  case SQUARE: return square(x);
317  case EPANECHNIKOV: return epanechnikov(x);
318  case POLYRAMP: return polyramp(x);
319  case INVSQRT: return invsqrt(x);
320  case COULOMB: return coulomb(x);
321  case STEP: return step(x);
322  default: return 0.;
323  }
324 }
325 
326 //\///////////////////////////////////////////////////////////////////////////
327 // general multi-dimensional evaluation function - what the public uses
328 //\///////////////////////////////////////////////////////////////////////////
329 
334 
344 template<int dim>
345 double elliptic(Wonton::Point<dim> const& x,
346  Wonton::Point<dim> const& y,
347  std::array<double,dim> const& h) {
348  double distance = 0.;
349  for (int i = 0; i < dim; i++) {
350  distance += (x[i] - y[i]) * (x[i] - y[i]) / (h[i] * h[i]);
351  }
352  return std::sqrt(distance);
353 }
354 
364 template<int dim>
365 std::array<double,dim> tensor(Wonton::Point<dim> const& x,
366  Wonton::Point<dim> const& y,
367  std::array<double,dim> const& h) {
368  std::array<double,dim> result;
369  for (int i = 0; i < dim; i++) {
370  result[i] = (x[i] - y[i]) / h[i];
371  }
372  return result;
373 }
374 
386 template<int dim>
387 double eval(Geometry const geometry,
388  Kernel const kern,
389  Wonton::Point<dim> const& x,
390  Wonton::Point<dim> const& y,
391  std::array<double,dim> const& h) {
392  double result = 0.;
393  double const norm = kernel(kern, 0.0);
394  switch (geometry) {
395  case ELLIPTIC: {
396  auto const arg = elliptic<dim>(x, y, h);
397  result = kernel(kern, arg) / norm;
398  break;
399  }
400  case TENSOR: {
401  result = 1.;
402  auto const arg = tensor<dim>(x, y, h);
403  for (int i = 0; i < dim; i++)
404  result *= kernel(kern, arg[i]) / norm;
405  break;
406  }
407  default:
408  throw std::runtime_error("invalid weight geometry");
409  }
410  return result;
411 }
412 
418 template<int dim>
419 struct FacetData {
420  double smoothing;
421  std::array<double,dim> normal;
422 };
423 
435 template<int dim>
436 double faceted(Kernel const kern,
437  Wonton::Point<dim> const& x,
438  Wonton::Point<dim> const& y,
439  std::vector<FacetData<dim>> const& facets,
440  size_t nsides) {
441  assert(kern == POLYRAMP or kern == STEP);
442  double result = 1.;
443  for (size_t i = 0; i < nsides; i++) {
444  double arg = 0.;
445  for (size_t j = 0; j < dim; j++)
446  arg += facets[i].normal[j] * (y[j] - x[j]);
447  arg /= facets[i].smoothing;
448  result *= kernel(kern, arg);
449  }
450  return result;
451 }
452 
464 template<int dim>
465 double eval(Geometry const geo,
466  Kernel const kern,
467  Wonton::Point<dim> const& x,
468  Wonton::Point<dim> const& y,
469  std::vector<std::vector<double>> const& vh) {
470  switch (geo) {
471  case TENSOR:
472  case ELLIPTIC: {
473  std::array<double,dim> h;
474  for (size_t i = 0; i < dim; i++)
475  h[i] = vh[0][i];
476  return eval<dim>(geo, kern, x, y, h);
477  }
478  case FACETED: {
479  int const nsides = vh.size();
480  std::vector<FacetData<dim>> facets(nsides);
481  for (int i = 0; i < nsides; i++) {
482  for (int j = 0; j < dim; j++)
483  facets[i].normal[j] = vh[i][j];
484  facets[i].smoothing = vh[i][dim];
485  }
486  return faceted<dim>(kern, x, y, facets, nsides);
487  }
488  default:
489  throw std::runtime_error("invalid weight geometry");
490  }
491 }
492 
493 }}} // namespace Portage::Meshfree::Weight
494 
495 #endif // PORTAGE_SUPPORT_WEIGHT_H_
double dcoulomb(double x)
coulomb weight derivative.
Definition: weight.h:267
double square(double x)
scalar square kernel.
Definition: weight.h:163
Definition: weight.h:304
std::vector< T > vector
Definition: portage.h:238
double depanechnikov(double x)
scalar epanechnikov kernel derivative.
Definition: weight.h:147
Definition: weight.h:304
double polyramp(double x)
scalar smooth ramp for faceted weight.
Definition: weight.h:187
double ddinvsqrt(double x)
second derivative of inverse square root kernel.
Definition: weight.h:247
double b4(double x)
scalar cubic b-spline.
Definition: weight.h:57
Definition: weight.h:304
std::array< double, dim > normal
Definition: weight.h:421
data for specifying a faceted weight.
Definition: weight.h:419
double invsqrt(double x)
inverse square root kernel.
Definition: weight.h:222
double coulomb(double x)
coulomb weight.
Definition: weight.h:259
double ddsquare(double x)
scalar square kernel second derivative.
Definition: weight.h:179
double ddstep(double x)
step weight second derivative.
Definition: weight.h:299
double const epsilon
Numerical tolerance.
Definition: weight.h:34
double db4(double x)
scalar cubic b-spline derivative.
Definition: weight.h:70
double elliptic(Wonton::Point< dim > const &x, Wonton::Point< dim > const &y, std::array< double, dim > const &h)
generic elliptically symmetric weight function argument.
Definition: weight.h:345
Definition: weight.h:304
Definition: weight.h:333
double eval(Geometry const geometry, Kernel const kern, Wonton::Point< dim > const &x, Wonton::Point< dim > const &y, std::array< double, dim > const &h)
evaluation function for elliptic or tensor product weights.
Definition: weight.h:387
double epanechnikov(double x)
scalar epanechnikov kernel.
Definition: weight.h:137
Geometry
Geometry types.
Definition: weight.h:333
double b4lh(double x)
scalar left half cubic b-spline.
Definition: weight.h:111
double ddcoulomb(double x)
coulomb weight second derivative.
Definition: weight.h:275
double smoothing
Definition: weight.h:420
double ib4(double x)
scalar cubic b-spline anti-derivative.
Definition: weight.h:94
Definition: coredriver.h:42
double ddb4(double x)
scalar cubic b-spline second derivative.
Definition: weight.h:82
double dinvsqrt(double x)
derivative of inverse square root kernel.
Definition: weight.h:234
double kernel(const Kernel kern, double x)
General kernel function.
Definition: weight.h:313
Definition: weight.h:333
double ddepanechnikov(double x)
scalar epanechnikov kernel second derivative.
Definition: weight.h:155
double dstep(double x)
step weight derivative.
Definition: weight.h:291
std::array< double, dim > tensor(Wonton::Point< dim > const &x, Wonton::Point< dim > const &y, std::array< double, dim > const &h)
generic tensor weight function arguments.
Definition: weight.h:365
double const normconst[4]
normalization constants for cubic B-spline (linear, cylindrical, and spherical).
Definition: weight.h:29
Kernel
Kernel types.
Definition: weight.h:304
double sign(double x)
scalar sign function.
Definition: weight.h:42
double ddpolyramp(double x)
scalar smooth ramp for faceted weight derivative.
Definition: weight.h:211
Definition: weight.h:304
double faceted(Kernel const kern, Wonton::Point< dim > const &x, Wonton::Point< dim > const &y, std::vector< FacetData< dim >> const &facets, size_t nsides)
faceted weight function
Definition: weight.h:436
double step(double x)
step weight.
Definition: weight.h:283
double dsquare(double x)
scalar square kernel derivative.
Definition: weight.h:171
Definition: weight.h:333
double dpolyramp(double x)
scalar smooth ramp for faceted weight derivative.
Definition: weight.h:200
double b4rh(double x)
scalar right half cubic b-spline.
Definition: weight.h:124
double unit_step(double x)
scalar step function
Definition: weight.h:45
Definition: weight.h:304