Source code for pygpc.BasisFunction

import scipy.special
import scipy.stats
import numpy as np
from .Quadrature import get_quadrature_jacobi_1d
from .Quadrature import get_quadrature_hermite_1d
from .Quadrature import get_quadrature_laguerre_1d
from .Grid import *


[docs] class BasisFunction(object): """ Abstract class of basis functions. This base class provides basic properties and methods for the basis functions. It cannot be used directly, but inherits properties and methods to the specific basis function sub classes. Parameters ---------- p : dict Parameters of the polynomial (see subclasses for details) """ def __init__(self, p): """ Constructor; initialized a Basis function class """ self.p = p self.fun = None self.fun_der = None self.fun_norm = None
[docs] def __call__(self, x, derivative=False): """ Evaluates basis function for argument x Parameters ---------- x : float or ndarray of float Argument for which the basis function is evaluated derivative : boolean, optional, default: False Returns derivative of basis function at argument x Returns ------- y : float or ndarray of float Function value or derivative of basis function at argument x """ if derivative: return self.fun_der(x) else: return self.fun(x)
[docs] class Jacobi(BasisFunction): """ Jacobi basis function used in the orthogonal gPC to model beta distributed random variables. Parameters ---------- p : dict Parameters of the Jacobi polynomial - p["i"] ... order - p["p"] ... first shape parameter - p["q"] ... second shape parameter """ def __init__(self, p): """ Constructor; initialized a Jacobi basis function """ super(Jacobi, self).__init__(p) # determine polynomial normalization factor beta_norm = (scipy.special.gamma(self.p["q"]) * scipy.special.gamma(self.p["p"]) / scipy.special.gamma(self.p["p"] + self.p["q"]) * 2.0 ** (self.p["p"] + self.p["q"] - 1)) ** (-1) jacobi_norm = 2 ** (self.p["p"] + self.p["q"] - 1) / ( (2.0 * self.p["i"] + self.p["p"] + self.p["q"] - 1)) * ( scipy.special.gamma(self.p["i"] + self.p["p"])) * ( scipy.special.gamma(self.p["i"] + self.p["q"])) / ( scipy.special.gamma(self.p["i"] + self.p["p"] + self.p["q"] - 1) * scipy.special.factorial(self.p["i"])) # normalization factor of polynomial (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = jacobi_norm * beta_norm # define basis function self.fun = scipy.special.jacobi(self.p["i"], self.p["q"] - 1, # beta-pdf: alpha=p /// jacobi-poly: alpha=q-1 !!! self.p["p"] - 1, # beta-pdf: beta=q /// jacobi-poly: beta=p-1 !!! monic=False) / np.sqrt(self.fun_norm) # derivative of polynomial self.fun_der = np.polyder(self.fun) # integral of fun and fun_der w.r.t. pdf (numerical integration with corresponding weights) knots, weights = get_quadrature_jacobi_1d(n=10 * self.p["i"], p=self.p["p"] - 1, q=self.p["q"] - 1) self.fun_int = np.dot(self.fun(knots), weights) self.fun_der_int = np.dot(self.fun_der(knots), weights)
[docs] class Hermite(BasisFunction): """ Hermite basis function used in the orthogonal gPC to model normal distributed random variables. Parameters ---------- p : dict Parameters of the Hermite polynomial - p["i"] ... order """ def __init__(self, p): """ Constructor; initializes a Hermite basis function """ super(Hermite, self).__init__(p) # normalization factor of polynomial (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = np.float64(scipy.special.factorial(p["i"])) # define basis function self.fun = scipy.special.hermitenorm(p["i"], monic=False) / np.sqrt(self.fun_norm) # derivative of polynomial self.fun_der = np.polyder(self.fun) # integral of fun and fun_der w.r.t. pdf (numerical integration with corresponding weights) if self.p["i"] == 0: self.fun_int = 1.0 self.fun_der_int = 0.0 else: knots, weights = get_quadrature_hermite_1d(n=10 * self.p["i"]) self.fun_int = np.dot(self.fun(knots), weights) self.fun_der_int = np.dot(self.fun_der(knots), weights)
[docs] class Laguerre(BasisFunction): """ Laguerre basis function used in the orthogonal gPC to model gamma distributed random variables. It is defined in the gpc space from [0, inf] Parameters ---------- p : dict Parameters of the Laguerre polynomial - p["i"] ... order - p["alpha"] ... shape parameter (alpha_poly = alpha_pdf - 1) - p["beta"] ... rate parameter """ def __init__(self, p): """ Constructor; initializes a Laguerre basis function """ super(Laguerre, self).__init__(p) self.fun_norm = (scipy.special.factorial(p["i"]+p["alpha"]) / scipy.special.factorial(p["i"])) / \ scipy.special.gamma(p["alpha"] + 1) # define basis function self.fun = scipy.special.genlaguerre(p["i"], alpha=p["alpha"], monic=False) / np.sqrt(self.fun_norm) # derivative of polynomial self.fun_der = np.polyder(self.fun) # integral of fun and fun_der w.r.t. pdf (numerical integration with corresponding weights) if self.p["i"] == 0: self.fun_int = 1.0 self.fun_der_int = 0.0 else: knots, weights = get_quadrature_laguerre_1d(n=10 * self.p["i"], alpha=p["alpha"]) self.fun_int = np.dot(self.fun(knots), weights) self.fun_der_int = np.dot(self.fun_der(knots), weights)
[docs] class StepUp(BasisFunction): """ StepUp (from 0 to 1) basis function used in the non-orthogonal gPC. Parameters ---------- p : dict Parameters of the StepUp function - p["xs"] ... location of step """ def __init__(self, p): """ Constructor; initializes a StepUp basis function """ super(StepUp, self).__init__(p) # normalization factor of function (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = 1.0 # define basis function self.fun = lambda x: 0.0 if x < p["xs"] else (0.5 if x == p["xs"] else 1.0) # derivative self.fun_der = lambda x: 0.0
[docs] class StepDown(BasisFunction): """ StepDown (from 1 to 0) basis function used in the non-orthogonal gPC. Parameters ---------- p : dict Parameters of the StepDown function - p["xs"] ... location of step """ def __init__(self, p): """ Constructor; initializes a StepDown basis function """ super(StepDown, self).__init__(p) # normalization factor of function (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = 1.0 # define basis function self.fun = lambda x: 1.0 if x < p["xs"] else (0.5 if x == p["xs"] else 0.0) # derivative self.fun_der = lambda x: 0.0
[docs] class Rect(BasisFunction): """ Rectangular basis function used in the non-orthogonal gPC. Parameters ---------- p : dict Parameters of the Rect function - p["x1"] ... location of positive flank (0 -> 1) - p["x2"] ... location of negative flank (1 -> 0) """ def __init__(self, p): """ Constructor; initializes a Rect basis function """ super(Rect, self).__init__(p) # normalization factor of function (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = 1.0 # define basis function self.fun = lambda x: 1.0 if p["x1"] < x < p["x2"] else (0.5 if x == p["x1"] or x == p["x2"] else 0.0) # derivative self.fun_der = lambda x: 0.0
[docs] class SigmoidUp(BasisFunction): """ SigmoidUp (from 0 to 1) basis function used in the non-orthogonal gPC. Parameters ---------- p : dict Parameters of the SigmoidUp function - p["xs"] ... location of turning point - p["r"] ... steepness """ def __init__(self, p): """ Constructor; initializes a SigmoidUp basis function """ super(SigmoidUp, self).__init__(p) # normalization factor of function (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = 1.0 # define basis function self.fun = lambda x: 1.0 / (1 + np.exp(-p["r"] * (x - p["xs"]))) # derivative self.fun_der = lambda x: (p["r"] * np.exp(-p["r"] * (x - p["xs"]))) / (1 + np.exp(-p["r"] * (x - p["xs"])))**2
[docs] class SigmoidDown(BasisFunction): """ SigmoidDown (from 0 to 1) basis function used in the non-orthogonal gPC. Parameters ---------- p : dict Parameters of the SigmoidDown function - p["xs"] ... location of turning point - p["r"] ... steepness """ def __init__(self, p): """ Constructor; initializes a SigmoidDown basis function """ super(SigmoidDown, self).__init__(p) # normalization factor of function (to later normalize basis functions <psi^2> = int(psi^2*p)dx) self.fun_norm = 1.0 # define basis function self.fun = lambda x: 1.0 / (1 + np.exp(-p["r"] * (- x + p["xs"]))) # derivative self.fun_der = lambda x: (- p["r"] * np.exp(-p["r"] * (- x + p["xs"]))) / (1 + np.exp(-p["r"] * (- x + p["xs"])))**2