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 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 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
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