Skip to content

Commit 3333ebb

Browse files
committed
small mods to Newton…
* added fdcoeffv.py to the repo as an extra python routine
1 parent d84dc8f commit 3333ebb

File tree

2 files changed

+74
-7
lines changed

2 files changed

+74
-7
lines changed

09_ODE_ivp_part2.ipynb

+10-7
Original file line numberDiff line numberDiff line change
@@ -2948,7 +2948,7 @@
29482948
"\n",
29492949
"$$\n",
29502950
"\\begin{align}\n",
2951-
" \\mathbf{F}(\\mathbf{x}+\\boldsymbol{\\delta})&= \\mathbf{b} - A\\mathbf{x_0} - A\\boldsymbol{\\delta} = \\mathbf{0}\\\\\n",
2951+
" \\mathbf{F}(\\mathbf{x}_0+\\boldsymbol{\\delta})&= \\mathbf{b} - A\\mathbf{x_0} - A\\boldsymbol{\\delta} = \\mathbf{0}\\\\\n",
29522952
" &=\\mathbf{F}(\\mathbf{x}_0) - A\\boldsymbol{\\delta} = \\mathbf{0}\\\\\n",
29532953
"\\end{align}\n",
29542954
"$$"
@@ -3222,15 +3222,16 @@
32223222
"outputs": [],
32233223
"source": [
32243224
"# Some quick and dirty Code\n",
3225-
"def newton(F,J,x0,tol=1.e-6,MAX_ITS=100):\n",
3225+
"def newton(F,J,x0,tol=1.e-6,MAX_ITS=100,verbose=True):\n",
32263226
" \"\"\" Solve F(x) = 0 using Newton's method until ||F(x)|| < tol or reaches Max iterations\"\"\"\n",
32273227
" \n",
32283228
" x = x0\n",
32293229
" for k in range(MAX_ITS+1):\n",
32303230
" delta = numpy.linalg.solve(J(x),-F(x))\n",
32313231
" x += delta\n",
32323232
" err = numpy.linalg.norm(F(x))\n",
3233-
" print('||F|| = {}'.format(err))\n",
3233+
" if verbose:\n",
3234+
" print('||F|| = {}'.format(err))\n",
32343235
" if err < tol: \n",
32353236
" return x, k\n",
32363237
" \n",
@@ -3310,13 +3311,15 @@
33103311
]
33113312
},
33123313
{
3313-
"cell_type": "code",
3314-
"execution_count": null,
3314+
"cell_type": "markdown",
33153315
"metadata": {
33163316
"hide_input": false
33173317
},
3318-
"outputs": [],
3319-
"source": []
3318+
"source": [
3319+
"### An Exercise: \n",
3320+
"\n",
3321+
"Write a BDF-2 scheme that can solve a general non-linear problem and test it using the vander-pol oscillator."
3322+
]
33203323
}
33213324
],
33223325
"metadata": {

fdcoeffV.py

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import numpy as numpy
2+
from scipy.special import factorial
3+
4+
def fdcoeffV(k,xbar,x):
5+
"""
6+
fdcoeffV routine modified from Leveque (2007) matlab function
7+
8+
Params:
9+
-------
10+
11+
k: int
12+
order of derivative
13+
xbar: float
14+
point at which derivative is to be evaluated
15+
x: ndarray
16+
numpy array of coordinates to use in calculating the weights
17+
18+
Returns:
19+
--------
20+
c: ndarray
21+
array of floats of coefficients.
22+
23+
Compute coefficients for finite difference approximation for the
24+
derivative of order k at xbar based on grid values at points in x.
25+
26+
WARNING: This approach is numerically unstable for large values of n since
27+
the Vandermonde matrix is poorly conditioned. Use fdcoeffF.m instead,
28+
which is based on Fornberg's method.
29+
30+
This function returns a row vector c of dimension 1 by n, where n=length(x),
31+
containing coefficients to approximate u^{(k)}(xbar),
32+
the k'th derivative of u evaluated at xbar, based on n values
33+
of u at x(1), x(2), ... x(n).
34+
35+
If U is an array containing u(x) at these n points, then
36+
c.dot(U) will give the approximation to u^{(k)}(xbar).
37+
38+
Note for k=0 this can be used to evaluate the interpolating polynomial
39+
itself.
40+
41+
Requires len(x) > k.
42+
Usually the elements x(i) are monotonically increasing
43+
and x(1) <= xbar <= x(n), but neither condition is required.
44+
The x values need not be equally spaced but must be distinct.
45+
46+
Modified rom http://www.amath.washington.edu/~rjl/fdmbook/ (2007)
47+
"""
48+
49+
50+
n = x.shape[0]
51+
assert k < n, " The order of the derivative must be less than the stencil width"
52+
53+
# Generate the Vandermonde matrix from the Taylor series
54+
A = numpy.ones((n,n))
55+
xrow = (x - xbar) # displacements x-xbar
56+
for i in range(1,n):
57+
A[i,:] = (xrow**(i))/factorial(i);
58+
59+
b = numpy.zeros(n) # b is right hand side,
60+
b[k] = 1 # so k'th derivative term remains
61+
62+
c = numpy.linalg.solve(A,b) # solve n by n system for coefficients
63+
64+
return c

0 commit comments

Comments
 (0)