Coverage for src/methodsnm/recpol.py: 55%
62 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-27 13:22 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-27 13:22 +0000
1from numpy import array
2from methodsnm.fe import *
4import numpy as np
5from abc import ABC, abstractmethod
7import matplotlib.pyplot as plt
10class RecursivePolynomial(ABC):
11 """
12 Abstract base class for recursive polynomial evaluation.
14 Polynomials are evaluated using the following recursion:
15 * d "starter" (given functions)
16 * P_i(x) = s_i(x) for i < d
17 * recursion formulate for i >= d:
18 * P_i(x) = sum_{j=0}^{d-1} c_j(i,x) P_{i-d+j}(x)
20 Attributes:
21 -----------
22 starter : list
23 List of starter functions.
24 rec_coeff : list
25 List of recursive coefficients.
26 """
27 starter = None
28 rec_coeff = None
30 @abstractmethod
31 def __init__(self):
32 pass
34 def evaluate_all(self, x, n):
35 """
36 Evaluates the recursive polynomial for all values of x up to n.
38 Parameters:
39 -----------
40 x : array_like
41 Array of values to evaluate the polynomial at.
42 n : int
43 Maximum degree of the polynomial to evaluate.
45 Returns:
46 --------
47 vals : ndarray
48 Array of shape (len(x), n+1 ) containing the values of the polynomial
49 evaluated at each value of x up to degree n.
50 """
51 vals = np.empty((len(x), n+1), dtype=x.dtype)
52 d = len(self.rec_coeff)
53 for si, s in enumerate(self.starter):
54 vals[:,si] = s(x)
55 for i in range(d, n+1):
56 vals[:,i] = sum([self.rec_coeff[j](i,x)*vals[:,i-d+j] for j in range(d)])
57 return vals
59 def evaluate(self, x, n):
60 """
61 Evaluate the recursive polynomial of degree n for all values of x.
63 Parameters:
64 -----------
65 x : array_like
66 Array of values to evaluate the polynomial at.
67 n : int
68 Degree of the polynomial to evaluate.
70 Returns:
71 --------
72 vals : ndarray
73 Array of length len(x) containing the values of the polynomial
74 evaluated at each value of x.
75 """
76 d = len(self.rec_coeff)
77 vals = np.empty((len(x), d+1))
78 for si, s in enumerate(self.starter):
79 vals[:,si] = s(x)
80 for i in range(d, n+1):
81 if i != d:
82 for j in range(d):
83 vals[:,j] = vals[:,j+1]
84 vals[:,d] = sum([self.rec_coeff[j](i,x)*vals[:,j] for j in range(d)])
85 return vals[:,d]
87 def plot_all(self, x, n):
88 """
89 Plots the recursive polynomial for all values of x up to n.
91 Parameters:
92 -----------
93 x : array_like
94 Array of values to evaluate the polynomial at.
95 n : int
96 Maximum degree of the polynomial to evaluate.
97 """
98 vals = self.evaluate_all(x, n)
99 for i in range(n+1):
100 plt.plot(x, vals[:,i], label="P_{}".format(i))
101 plt.legend()
102 plt.show()
105class Monomials(RecursivePolynomial):
106 def __init__(self):
107 self.starter = [lambda x: np.ones_like(x)]
108 self.rec_coeff = [lambda n,x: x]
110class LegendrePolynomials(RecursivePolynomial):
111 def __init__(self):
112 self.starter = [lambda x: x**0, lambda x: x]
113 self.rec_coeff = [lambda n,x: -(n-1)/n, lambda n,x: (2*n-1)/n*x]
115class JacobiPolynomials(RecursivePolynomial):
116 alpha = None
117 beta = None
118 def __init__(self, alpha, beta):
119 self.alpha = alpha
120 self.beta = beta
121 self.starter = [lambda x: np.ones_like(x), lambda x: alpha+1+(alpha+beta+2)/2*(x-1)]
122 def c0(n,x):
123 alpha, beta = self.alpha, self.beta
124 return -2*(n+alpha-1)*(n+beta-1)*(2*n+alpha+beta)/((2*n+alpha+beta-2)*(n+alpha+beta)*2*n)
125 def c1(n,x):
126 alpha, beta = self.alpha, self.beta
127 return (2*n+alpha+beta-1)*((2*n+alpha+beta)*(2*n+alpha+beta-2)*x+alpha**2-beta**2)/((2*n+alpha+beta-2)*(n+alpha+beta)*2*n)
128 self.rec_coeff = [c0, c1]
130class IntegratedLegendrePolynomials(RecursivePolynomial):
131 def __init__(self):
132 self.starter = [lambda x: x, lambda x: 0.5*(x**2-1)]
133 self.rec_coeff = [lambda n,x: -(n-2)/n, lambda n,x: (2*n-3)/n*x]