def Nystrom(k): r""" Construct the k-step explicit Nystrom linear multistep method. The methods are explicit and have order k. They have the form: `y_{n+1} = y_{n-1} + h \sum_{j=0}^{k-1} \beta_j f(y_n-k+j+1)` They are generated using equations (1.13) and (1.7) from [hairer1993]_ III.1, along with the binomial expansion and the relation in exercise 4 on p. 367. Note that the term "Nystrom method" is also commonly used to refer to a class of methods for second-order ODEs; those are NOT the methods generated by this function. **Examples**:: >>> import nodepy.linear_multistep_method as lm >>> nys3=lm.Nystrom(6) >>> nys3.order() 6 References: #. [hairer1993]_ """ import sympy from sympy import Rational one = Rational(1, 1) alpha = snp.zeros(k + 1) alpha[k] = one alpha[k - 2] = -one beta = snp.zeros(k + 1) kappa = snp.zeros(k) gamma = snp.zeros(k) gamma[0] = one kappa[0] = 2 * one beta[k - 1] = 2 * one betaj = snp.zeros(k + 1) for j in range(1, k): gamma[j] = one - sum(gamma[:j] / snp.arange(j + 1, 1, -1)) kappa[j] = 2 * gamma[j] - gamma[j - 1] for i in range(0, j + 1): betaj[k - i - 1] = (-one)**i * sympy.combinatorial.factorials.binomial( j, i) * kappa[j] beta = beta + betaj name = str(k) + '-step Nystrom' return LinearMultistepMethod(alpha, beta, name=name, shortname='Nys' + str(k))
def Milne_Simpson(k): r""" Construct the k-step, Milne-Simpson method. The methods are implicit and (for k>=3) have order k+1. They have the form: `y_{n+1} = y_{n-1} + h \sum_{j=0}^{k} \beta_j f(y_n-k+j+1)` They are generated using equation (1.15), the equation in Exercise 3, and the relation in exercise 4, all from Hairer & Wanner III.1, along with the binomial expansion. **Examples**:: >>> import nodepy.linear_multistep_method as lm >>> ms3=lm.Milne_Simpson(3) >>> ms3.order() 4 References: [hairer1993]_ """ import sympy alpha = snp.zeros(k + 1) beta = snp.zeros(k + 1) alpha[k] = 1 alpha[k - 2] = -1 gamma = snp.zeros(k + 1) kappa = snp.zeros(k + 1) gamma[0] = 1 kappa[0] = 2 beta[k] = 2 betaj = snp.zeros(k + 1) for j in range(1, k + 1): gamma[j] = -sum(gamma[:j] / snp.arange(j + 1, 1, -1)) kappa[j] = 2 * gamma[j] - gamma[j - 1] for i in range(0, j + 1): betaj[k - i] = (-1)**i * sympy.combinatorial.factorials.binomial( j, i) * kappa[j] beta = beta + betaj name = str(k) + '-step Milne-Simpson' return LinearMultistepMethod(alpha, beta, name=name, shortname='MS' + str(k))
def Adams_Bashforth(k): r""" Construct the k-step, Adams-Bashforth method. The methods are explicit and have order k. They have the form: `y_{n+1} = y_n + h \sum_{j=0}^{k-1} \beta_j f(y_n-k+j+1)` They are generated using equations (1.5) and (1.7) from [hairer1993]_ III.1, along with the binomial expansion. **Examples**:: >>> import nodepy.linear_multistep_method as lm >>> ab3=lm.Adams_Bashforth(3) >>> ab3.order() 3 References: #. [hairer1993]_ """ import sympy from sympy import Rational one = Rational(1, 1) alpha = snp.zeros(k + 1) beta = snp.zeros(k + 1) alpha[k] = one alpha[k - 1] = -one gamma = snp.zeros(k) gamma[0] = one beta[k - 1] = one betaj = snp.zeros(k + 1) for j in range(1, k): gamma[j] = one - sum(gamma[:j] / snp.arange(j + 1, 1, -1)) for i in range(0, j + 1): betaj[k - i - 1] = (-one)**i * sympy.combinatorial.factorials.binomial( j, i) * gamma[j] beta = beta + betaj name = str(k) + '-step Adams-Bashforth' return LinearMultistepMethod(alpha, beta, name=name, shortname='AB' + str(k))
def Adams_Moulton(k): r""" Construct the k-step, Adams-Moulton method. The methods are implicit and have order k+1. They have the form: `y_{n+1} = y_n + h \sum_{j=0}^{k} \beta_j f(y_n-k+j+1)` They are generated using equation (1.9) and the equation in Exercise 3 from Hairer & Wanner III.1, along with the binomial expansion. **Examples**:: >>> import nodepy.linear_multistep_method as lm >>> am3=lm.Adams_Moulton(3) >>> am3.order() 4 References: [hairer1993]_ """ import sympy alpha = snp.zeros(k + 1) beta = snp.zeros(k + 1) alpha[k] = 1 alpha[k - 1] = -1 gamma = snp.zeros(k + 1) gamma[0] = 1 beta[k] = 1 betaj = snp.zeros(k + 1) for j in range(1, k + 1): gamma[j] = -sum(gamma[:j] / snp.arange(j + 1, 1, -1)) for i in range(0, j + 1): betaj[k - i] = (-1)**i * sympy.combinatorial.factorials.binomial( j, i) * gamma[j] beta = beta + betaj name = str(k) + '-step Adams-Moulton' return LinearMultistepMethod(alpha, beta, name=name, shortname='AM' + str(k))
def _satisfies_order_conditions(self, p, tol): """ Return True if the linear multistep method satisfies the conditions of order p (only) """ ii = snp.arange(len(self.alpha)) return abs(sum(ii**p * self.alpha - p * self.beta * ii**(p - 1))) < tol