pops-core  0.9
PoPS (Pest or Pathogen Spread) Model Core C++ library
lognormal_kernel.hpp
Go to the documentation of this file.
1 /*
2  * PoPS model - log normal dispersal kernel
3  *
4  * Copyright (C) 2015-2020 by the authors.
5  *
6  * Authors: Margaret Lawrimore malawrim ncsu edu
7  *
8  * The code contained herein is licensed under the GNU General Public
9  * License. You may obtain a copy of the GNU General Public License
10  * Version 2 or later at the following locations:
11  *
12  * http://www.opensource.org/licenses/gpl-license.html
13  * http://www.gnu.org/copyleft/gpl.html
14  */
15 
16 #ifndef POPS_LOGNORMAL_KERNEL_HPP
17 #define POPS_LOGNORMAL_KERNEL_HPP
18 
19 #include "kernel_types.hpp"
20 #include "raster.hpp"
21 #include "utils.hpp"
22 
23 #include <random>
24 
25 namespace pops {
26 
27 using std::pow;
28 using std::exp;
29 using std::log;
30 using std::sqrt;
31 
36 {
37 protected:
38  double sigma;
39  std::lognormal_distribution<double> lognormal_distribution;
40 
41 public:
43  {
44  if (sigma <= 0) {
45  throw std::invalid_argument("sigma must be greater than 0.0");
46  }
47  }
48 
55  template<class Generator>
56  double random(Generator& generator)
57  {
58  return std::abs(lognormal_distribution(generator));
59  }
60 
67  double pdf(double x)
68  {
69  if (x < 0) {
70  throw std::invalid_argument("x must be greater than or equal to 0.0");
71  }
72  if (x == 0) {
73  return 0;
74  }
75  return (1 / (x * sigma * sqrt(2 * M_PI)))
76  * exp(-(pow(log(x), 2)) / (2 * pow(sigma, 2)));
77  }
78 
87  double icdf(double x)
88  {
89  if (x <= 0 || x >= 1) {
90  throw std::invalid_argument("icdf: x must be between 0.0 and 1.0");
91  }
92  // approximation for inverse error function
93  double y = (2 * x) - 1;
94  float sign = (y < 0) ? -1.0f : 1.0f;
95  // 0.147 used for a relative error of about 2*10^-3
96  // float b = 2 / (M_PI * 0.147) + 0.5f * log(1 - pow(y, 2));
97  // double inverf =
98  // (sign * sqrt(-b + sqrt(pow(b, 2) - (1 / (0.147) * log(1 - pow(y, 2))))));
99  double a = 0.140012;
100  double t = 2.0 / (M_PI * a);
101  double l = log(1 - pow(y, 2));
102  double inverf =
103  sign * sqrt(sqrt(pow(t + (l / 2.0), 2) - (l / a)) - (t + (l / 2.0)));
104  return exp(sqrt(2 * pow(sigma, 2)) * inverf);
105  }
106 };
107 
108 } // namespace pops
109 
110 #endif // POPS_LOGNORMAL_KERNEL_HPP
raster.hpp
utils.hpp
M_PI
#define M_PI
Definition: utils.hpp:35
pops
Definition: cauchy_kernel.hpp:25
pops::LogNormalKernel::LogNormalKernel
LogNormalKernel(double s)
Definition: lognormal_kernel.hpp:42
pops::LogNormalKernel::sigma
double sigma
Definition: lognormal_kernel.hpp:38
pops::LogNormalKernel::pdf
double pdf(double x)
Log normal probability density function Used by DeterministicKernel to determine location of spread.
Definition: lognormal_kernel.hpp:67
pops::LogNormalKernel
Dispersal kernel for log normal distribution class utilized by RadialKernel and DeterministicKernel.
Definition: lognormal_kernel.hpp:35
pops::LogNormalKernel::lognormal_distribution
std::lognormal_distribution< double > lognormal_distribution
Definition: lognormal_kernel.hpp:39
pops::LogNormalKernel::icdf
double icdf(double x)
Log normal inverse cumulative distribution (quantile) function Used by DeterministicKernel to determi...
Definition: lognormal_kernel.hpp:87
pops::LogNormalKernel::random
double random(Generator &generator)
Returns random value from log normal distribution Used by RadialKernel to determine location of sprea...
Definition: lognormal_kernel.hpp:56
kernel_types.hpp
Kernel types enum and helper functions.