numerical analysis using m#math€¦ · // gauss-jordan elimination without pivot ... // gauss...
TRANSCRIPT
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
1
"msharpmath" revised 2012.12.06
Numerical Analysis Using M#math
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// user functions for Numerical Analysis
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
click a line and move to the definition
// matrix adaptive_ode(double tol, t,tf,h, matrix y,fun(double t,matrix y))
// poly bairstow(a, double r,s)
// double bisect(a,b, f(x))
// complex cnewton(z, cftn(z),cftn2(z))
// matrix divdiff(&x,&f)
// double dnewton(x, ftn(x))
// matrix eig22(A)
// void eighot(matrix A)
// double eiginvpow(matrix A, &x)
// void eigjac(matrix A)
// matrix eiglast(&A)
// poly eigpol(matrix& A)
// double eigpow(matrix A, &x)
// matrix gausselim(A)
// matrix gaussjord(A)
// matrix gausspivot(A)
// double falsePos(a,b, f(x))
// double hermite(xx, matrix &x,&y,&y1)
// integ(a,b,f(x))
// matrix jordelim(A)
// double lagran(matrix x,f, double xx)
// double modfalsePos(a,b, f(x))
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
2
// double muller(a,b,c, f(x))
// poly polreg(matrix &x,&f, double n)
// double reldiff(a,b) = |a-b|/(1+|a|+|b|);
// matrix seidel(&A,b)
// void spline3(matrix &x,&f,poly *P)
// poly tcheby(double a,b,n, f(x))
// matrix user_tdma(a,b,c,d, double na,nb)
// double user_tdmares(matrix x, &a, &b, &c, &d)
// void user_chol(matrix& A)
// matrix user_hess(A)
// void user_lu(matrix& A)
// matrix user_ode(double t,tf,h, matrix y,fun(double t,matrix y))
// matrix user_qr(matrix& A)
// void bvp2nd(double a,b,nx, matrix &x,&f,&u)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 1 Introduction
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 2 Solution of Nonlinear Equations
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
double reldiff(a,b) = |a-b|/(1+|a|+|b|);
// relative difference, a.-.b
double bisect(a,b, ftn(x)) {
eps = 1.e-6;
ya = ftn(a); if( |ya| < eps ) return a;
yb = ftn(b); if( |yb| < eps ) return b;
if( ya*yb > 0 ) { "y(a)y(b) > 0"; return NaN; }
iter = 0;
while(1) {
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
3
if( ++iter > 200 ) { "bisection failed"; return NaN; }
x = 0.5*(a+b);
y = ftn(x);
[ iter,a,b,x,y ];; // display with double semicolons ;;
if( |y| > inf ) { "bisection diverged"; return NaN; }
if( reldiff(a,b) < eps || |y| < eps ) break;
if( ya*y > 0 ) a = x;
else b = x;
}
return x;
}
#> reldiff;
#> bisect;
//----------------------------------------------------------------------
// Newton method
//----------------------------------------------------------------------
double dnewton(x, ftn(x)) {
eps = 1.e-6;
y = ftn(x); if( |y| < eps ) return x;
iter = 0;
while(1) {
if( ++iter > 200 ) { "newton solver failed"; return NaN; }
deno = ftn'(x); // derivative
if( |deno| < eps ) { "dfdx ~= 0"; return NaN; }
dx = -y / deno;
x += dx;
y = ftn(x);
[ iter,x,y ];; // display
if( x.-.(x-dx) < eps || |y| < eps ) break; // a.-.b
}
return x;
}
#> dnewton;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
4
//----------------------------------------------------------------------
// Complex Newton method, cftn = complex function
//----------------------------------------------------------------------
complex cnewton(z, cftn(z),cftn2(z)) {
eps = 1.e-6;
w = cftn(z); if( |w| < eps ) return z;
iter = 0;
while(1) {
if( ++iter > 200 ) { "newton-solver failed"; return NaN ! ; }
deno = cftn2(z); // derivative must be given by argument
if( |deno| < eps ) { "dfdx ~= 0"; return NaN !; }
dz = -w / deno;
z += dz;
w = cftn(z);
[ iter, z, |w| ];; // display
if( |dz| < eps || |w| < eps ) break;
}
return z;
}
#> cnewton;
//----------------------------------------------------------------------
// false position method
//----------------------------------------------------------------------
double falsePos(a,b, ftn(x)) {
eps = 1.e-6;
ya = ftn(a); if( |ya| < eps ) return a;
yb = ftn(b); if( |yb| < eps ) return b;
if( ya*yb > 0 ) { "y(a)y(b) > 0"; return NaN; }
iter = 0;
while(1) {
if( ++iter > 200 ) { "false-position failed"; return NaN; }
x = a-ya*(a-b)/(ya-yb);
y = ftn(x);
[ iter,a,b,x,y ];; // display
if( |y| > inf ) { "false-position failed"; return NaN; }
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
5
if( a.-.b < eps || |y| < eps ) break;
// relative difference a.-.b
if( ya*y > 0 ) { a = x; ya = y; }
else { b = x; yb = y; }
}
return x;
}
#> falsePos;
//----------------------------------------------------------------------
// modified false position method
//----------------------------------------------------------------------
double modfalsePos(a,b, ftn(x)) {
eps = 1.e-6;
ya = ftn(a); if( |ya| < eps ) return a;
yb = ftn(b); if( |yb| < eps ) return b;
yc = ya;
if( ya*yb > 0 ) { "y(a)y(b) > 0"; return NaN; }
iter = 0;
while(1) {
if( ++iter > 200 ) { "modified false position failed"; return NaN; }
x = a-ya*(a-b)/(ya-yb);
y = ftn (x);
[ iter,a,b,x,y];; // display
if( |y| > inf ) { "modified false position failed"; return NaN; }
if( a.-.b < eps || |y| < eps ) break;
if( ya*y > 0 ) { a = x; ya = y; if( ya*yc > 0 ) yb *= 0.5; }
else { b = x; yb = y; if( yc*yb > 0 ) ya *= 0.5; }
}
return x;
}
#> modfalsePos;
//----------------------------------------------------------------------
// Muller method
//----------------------------------------------------------------------
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
6
double muller(a,b,c, ftn(x)) {
eps = 1.e-7;
x = [a,b,c];
y = ftn++(x); // upgrade ‘double’ function to accept matrix
iter=0;
while(1) {
if(++iter > 100) { "muller failed"; return NaN; }
k = 6 - x.max1k - x.min1k; // median index of x1,x2,x3
p = .interp(x,y) %% x(k); // synthetic division
a = p[2]; b = p[1]; c = p[0];
det = b*b-4*a*c;
if(det < 0) { "no real root in muller";; return NaN; }
if(b > 0) xx = x(k)-2*c/(b+sqrt(det));
else xx = x(k)-2*c/(b-sqrt(det)); // root of a quadratic, eq(45)
yy = ftn(xx);
d = |x-xx|.max1;
k = |x-xx|.max1k;
x(k) = xx; // find and discard the farthermost point from xx
y(k) = yy; // replace the discarded point with the root xx
[ x, xx, yy ];; // display
if( |d| < eps || |yy| < eps ) break;
}
return xx;
}
#> muller;
//----------------------------------------------------------------------
// Bairstow method
//----------------------------------------------------------------------
poly bairstow(a, double r,s) { // poly bairstow(poly a, double r,s)
a = a.monic; // make a leading coefficient a_n = 1
n = a.n;
double b[100],br[100],bs[100];
b = 0; br = 0; bs = 0;
iter = 0;
for[500] {
b[n] = a[n];
b[n-1] = a[n-1]-r*b[n];
for.i(n-2,1, -1) b[i] = a[i]-r*b[i+1]-s*b[i+2]; // for(i=n-2; i>=1; i--)
b[0] = a[0]-s*b[2];
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
7
br[n-1] = -b[n];
br[n-2] = -b[n-1]-r*br[n-1]; bs[n-2] = -b[n];
for.i(n-3,1, -1) { // for(i = n-3; i >= 1; i--)
br[i] = -b[i+1]-r*br[i+1]-s*br[i+2];
bs[i] = -b[i+2]-s*bs[i+2]-r*bs[i+1];
}
br[0] = -s*br[2];
bs[0] = -b[2]-s*bs[2];
det = br[0]*bs[1]-br[1]*bs[0];
dr = (-b[0]*bs[1]+b[1]*bs[0])/det;
ds = (-b[1]*br[0]+b[0]*br[1])/det;
r += dr; s += ds;
[ iter, r, s ];;
if( |dr|+|ds| < 1.e-6 ) break; }
return poly(s,r,1);
}
#> bairstow;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 3 Numerical Linear Algebra
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cut;
"Chapter 3";
//----------------------------------------------------------------------
// Gauss-elimination, user code for A.gausselim
//----------------------------------------------------------------------
matrix gausselim(A) { // copy A
n = A.m;
for.k(1,n-1) { // for(k = 1; k < n; k++)
if( |A(k,k)| < _eps ) break;
prow = A.row(k)/A(k,k);
for.i(k+1,n) { // for(i = k+1; i <= n; i++)
A.row(i) -= A(i,k)*prow; A(i,k) = 0;
A;; // display
}
cut;;
}
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
8
return A;
}
#> gausselim;
//----------------------------------------------------------------------
// Gauss-Jordan elimination without pivot
//----------------------------------------------------------------------
matrix jordelim(A) { // copy A
n = A.m;
for.k(1,n) { // for(k = 1; k <= n; k++)
if( |A(k,k)| < _eps ) break; // _eps = 2.22e-16
A.row(k) /= A(k,k);
for.i(1,n) { // for(i = 1; i <= n; i++)
if( i == k ) continue; // skip if k=i
A.row(i) -= A(i,k)*A.row(k);
A(i,k) = 0.;
A;; // display
}
cut;;
}
return A;
}
#> jordelim;
//----------------------------------------------------------------------
// Gauss-Jordan elimination with pivot, user code for A.gaussjord
//----------------------------------------------------------------------
matrix gaussjord(A) { // copy A
n = A.m;
for.k(1,n) { // for(k = 1; k <= n; k++) up to the last line
// pivoting procedure below
//imax = k;
//pmax = |A(k,k)|;
//for(i = k+1; i <= n; i++) {
// if( pmax < |A(i,k)| ) { pmax = |A(i,k)|; imax = i; }
//}
imax = A..(k:n)(k).maxentryk +k-1; // maxentryk
if( imax != k ) { [ k,imax ];; A = A.swap(imax,k);; }
// elimination procedure
if( |A(k,k)| < _eps ) continue; // _eps = 2.22e-16
A.row(k) /= A(k,k);
for.i(1,n) { // for(i = 1; i <= n; i++)
if( i == k ) continue; // skip if k=i
A.row(i) -= A(i,k)*A.row(k);
A(i,k) = 0.;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
9
A;; // display
}
cut;;
}
return A;
}
#> gaussjord;
//----------------------------------------------------------------------
// Gauss elimination with pivot, user code for A.gausspivot
//----------------------------------------------------------------------
matrix gausspivot(A) { // copy A
n = A.m;
for.k(1,n-1) { // for(k = 1; k < n; k++)
// pivoting procedure below
//imax = k;
//pmax = |A(k,k)|;
//for(i = k+1; i <= n; i++) {
// if( pmax < |A(i,k)| ) { pmax = |A(i,k)|; imax = i; }
//}
imax = A..(k:n)(k).maxentryk +k-1; // maxentryk
if( imax != k ) { [ k,imax ];; A = A.swap(imax,k);; }
// elimination procedure
if( |A(k,k)| < _eps ) continue; // _eps = 2.22e-16
prow = A.row(k)/A(k,k);
for.i(k+1,n) { // for(i = k+1; i <= n; i++)
A.row(i) -= A(i,k)*prow;
A(i,k) = 0.;
A;; // display
}
cut;;
}
return A; }
#> gausspivot;
//----------------------------------------------------------------------
// Gauss-Seidel iteration procedure
//----------------------------------------------------------------------
matrix seidel(&A,b) { // refer A, copy b
n = A.n;
x = .zeros(n,1);
d = A.diag(0);
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
10
for.iter(1,10000) {
delx = ( b - A*x ) ./ d;
x += delx;
sum = delx.norm2;
if( iter <= 2 ) { x.tr ;; } // display ;;
if( sum < 1.e-6 ) { iter;; break; } // display ;;
}
return x;
}
#> seidel;
//----------------------------------------------------------------------
// tridiagonal matrix algorithm (TDMA)
// a(i)*x(i) + b(i)*x(i-1) + c(i)*x(i+1) = d(i), b(1) = c(n) = 0
//----------------------------------------------------------------------
matrix user_tdma(a,b,c,d, double na,nb) {
n = a.mn;
P = Q = x = .zeros(1,n);
P(na) = -c(na)/a(na);
Q(na) = d(na)/a(na);
for.i(na+1,nb) { // for(i = na+1; i <= nb; i++)
den = 1/( a(i) + b(i)*P(i-1) + _eps );
P(i) = -c(i) * den;
Q(i) = (d(i) - b(i) * Q(i-1))*den;
}
x(nb) = Q(nb);
for.i(nb-1,na,-1) x(i) = P(i)*x(i+1)+Q(i); // for(i = nb-1; i >= na; i--)
return x;
}
#> user_tdma;
//----------------------------------------------------------------------
// residue of tridiagonal matrix algorithm (TDMA)
// a(i)*x(i) + b(i)*x(i-1) + c(i)*x(i+1) = d(i), b(1) = c(n) = 0
//----------------------------------------------------------------------
double user_tdmares(matrix x, &a, &b, &c, &d) {
n = a.mn;
res = d(1)-a(1)*x(1)-c(1)*x(2)
+ d(n)-a(n)*x(n)-b(n)*x(n-1);
for.i(2,n-1) { // for(i = 2; i < n; i++)
res += d(i) - a(i)*x(i) - b(i)*x(i-1) - c(i)*x(i+1);
}
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
11
return res;
}
#> user_tdmares;
//----------------------------------------------------------------------
// LU decomposition
//----------------------------------------------------------------------
void user_lu(matrix& A) {
n = A.m;
L = U = .zeros(n);
for.s(1,n) { // for(s=1; s<=n; s++)
for.i(s,n) L(i,s) = A(i,s) - L..(i)(1:s-1) ** U..(1:s-1)(s);
U(s,s) = 1; // horizontal direction
for.j(s+1,n) U(s,j) = (A(s,j) - L..(s)(1:s-1) ** U..(1:s-1)(j))/L(s,s);
[ L, U ] ;; // display L..(j:n)(j), U..(i)(i:n)
}
}
#> user_lu;
//----------------------------------------------------------------------
// Choleski decomposition
//----------------------------------------------------------------------
void user_chol(matrix& A) {
n = A.m;
U = .zeros(n);
for.i(1,n) {
sum = A(i,i) - U..(1:i-1)(i).norm22;
if( sum < 0 ) { "negative diagonal in Choleski";; break; }
U(i,i) = sqrt(sum);
for.j(i+1,n) U(i,j) = (A(i,j) - U..(1:i-1)(i) ** U..(1:i-1)(j))/U(i,i);
U ;; // display U..(i)(i:n)
}
}
#> user_chol;
//----------------------------------------------------------------------
// QR decomposition
//----------------------------------------------------------------------
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
12
matrix user_qr(matrix& A) {
n = A.m;
Q = A.unit;
S = .I(n);
for.i(2,n) { // for(i=2; i<=n; i++) {
x = Q.col(i-1);
S -= x * x.tr;
Q.col(i) = ( S * Q.col(i) ).unit.trun12; }
return Q;
}
#> user_qr;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 4 Matrix Eigenvalue Problems
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cut;
"Chapter 4";
//----------------------------------------------------------------------
// user function equivalent to ‘A.eigpoly’
//----------------------------------------------------------------------
poly eigpol(matrix& A) {
n = A.m;
c = -(1:n+1).apoly; // to make c[n] = -1
B = A;
c[n-1] = B.trace;
for.k(2,n) {
B = A*(B-c[n-k+1]*.I(n)) ;; // display
c[n-k] = B.trace/k ; }
return -c; }
#> eigpol;
//------------------------------------------------
// power method
//------------------------------------------------
double eigpow(matrix A, &x) { // A is copied, x is referred,
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
13
lam = k = 0 ;
x = .ones(A.m,1);
while( 1 ) {
lamo = lam;
y = A * x ;
[ ++k, lam = y.maxentry , (x = y / lam )' ] ;; // to display
if( lam ~= lamo ) break; // 6 digits identical
}
return lam;
}
#> eigpow;
//------------------------------------------------
// inverse power method
//------------------------------------------------
double eiginvpow(matrix A, &x) { // A is copied, x is referred,
lam = k = 0 ;
x = .ones(A.m,1);
while( 1 ) {
lamo = lam;
y = A \ x ;
[ ++k, lam = y.maxentry , (x = y / lam )' ] ;; // to display
if( lam .-. lamo < 1.e-6 ) break; // relative difference
}
return 1 / lam;
}
#> eiginvpow;
//------------------------------------------------
// Householder PAP transformation into Hessenberg form
//------------------------------------------------
matrix user_hess(A) { // A is copied
n = A.m;
for.k(1,n-2) {
gamma = A(k+1,k).sign * A..(k+1 : n)(k).norm2;
alpha = 1/(gamma*(gamma+A(k+1,k)));
u = A.col(k);
u.(1:k) = 0; // u.entry(1:k) = 0;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
14
u(k+1) += gamma;
P = .I(n) - alpha * u*u';
A = (P*A*P).trun12;; // display
}
return A;
}
#> user_hess;
//------------------------------------------------
// eigenvalues from the last 2 x 2 submatrix at the right-bottom
//------------------------------------------------
matrix eig22(A) {
a1 = A.trace;
d = a1^2 - 4 * A.det; // x^2 - a1 x + a2 = 0
if( d < 0 ) return [ 0.5*(a1-sqrt(-d)!); 0.5*(a1+sqrt(-d)!) ];
else return [ 0.5*(a1-sqrt( d)) ; 0.5*(a1+sqrt( d)) ];
}
matrix eiglast(&A) {
n = A.n;
if( n == 1 ) return A;
else if( n == 2) eig22(A);
for.iter(0,99) {
A22 = A..(n-1:n)(n-1:n);
(Q,R) = (A*A - A22.trace *A + A22.det *.I(n) ) .qr;
A = Q'*A*Q;; // display
if( |A..(n-1:n)(1:n-2).maxentry| < 1.e-6 ) break;
}
return eig22( A..(n-1:n)(n-1:n) ); // last 2 x 2 matrix
}
#> eiglast;
//------------------------------------------------
// Hotelling Deflation Method
//------------------------------------------------
void eighot(matrix A) {
n = A.m;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
15
x = .ones(n,1);
lam = .zeros(n,1);
X = .zeros(n,n);
for.k(1,n) {
lam(k) = eigpow(A,x);
X.col(k) = x;
x = x.unit;
A -= lam(k)*x*x';
}
cut;; lam;; X;; // display
}
#> eighot;
//------------------------------------------------
// Jacobi Method
//------------------------------------------------
void eigjac(matrix A) {
eps = 1.e-7;
n = A.m;
X = .I(n);
iter=0;
while(1) {
if(++iter > 100) { "failed in eigenjac";; break; }
grs = 0;
for.i(1,n-1)
for.j(i+1,n)
if(|A(i,j)| > grs) { grs = |A(i,j)|; r = i; s = j; }
if( |grs| < eps ) break;
grr = A(r,r); gss = A(s,s); grs = A(r,s);
if( grr ~= gss ) theta = 0.25*pi;
else theta = 0.5*atan(2*grs/(grr-gss));
cost = cos(theta);
sint = sin(theta);
A(r,r) = grr*cost*cost+gss*sint*sint+2*grs*sint*cost;
A(s,s) = gss*cost*cost+grr*sint*sint-2*grs*sint*cost;
A(r,s) = A(s,r) = 0;
for.i(1,n) {
if(i != r && i != s) {
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
16
gr = A(i,r); gs = A(i,s);
A(i,r) = A(r,i) = gr*cost+gs*sint;
A(i,s) = A(s,i) = gs*cost-gr*sint;
}
gr=X(i,r); gs=X(i,s);
X(i,r) = gr*cost+gs*sint;
X(i,s) = gs*cost-gr*sint;
}
if( iter == 1 ) { grs;; r;; s;; theta;; cost;; sint;; A;; X;; }
[ iter, theta, r, s ];; // just for comment
}
cut;; A.trun8;; X;; // display
}
#> eigjac;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 5 Interpolation and Curve Fitting
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cut;
"Chapter 5";
//----------------------------------------------------------------------
// Lagrangian interpolation
//----------------------------------------------------------------------
double lagran(matrix x,f, double xx)
{
n = x.len;
yx = 0;
for.i(1,n) {
val = f(i);
for.j(1,n) if( i != j ) val *= (xx-x(j))/(x(i)-x(j));
yx += val;
}
return yx;
}
#> lagran;
//----------------------------------------------------------------------
// divided difference table
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
17
//----------------------------------------------------------------------
matrix divdiff(&x,&f)
{
n = x.len;
tab = f._1; // compulsory column vector
for.j(2,n) {
tab |= 0; // one more column initialized by zero
for.i(1,n-j+1) tab(i,j) = (tab(i+1,j-1)-tab(i,j-1))/(x(i+j-1)-x(i));
}
return tab;
}
//----------------------------------------------------------------------
// polynomial regression
//----------------------------------------------------------------------
%> UU'a = Uf, polynomial regression
poly polreg(matrix &x,&f, double n) {
U = x.vander(n);
p = poly((U*U') \ (U*f')) ; // from matrix to poly
return p;
}
#> polreg;
//----------------------------------------------------------------------
// spline interpolation
//----------------------------------------------------------------------
void spline3(matrix &x,&f,poly *P) {
// polynomial array must be a priori declared
n = x.len;
a = b = c = d = .zeros(1,n);
for.i(2,n-1) {
b(i) = x(i)-x(i-1);
c(i) = x(i+1)-x(i);
a(i) = 2*(b(i)+c(i));
d(i) = 6*( (f(i+1)-f(i))/c(i) - (f(i)-f(i-1))/b(i) );
}
icase = 0; // natural condition is default
if( icase == 1 ) { a(2) += b(2); a(n-1) += c(n-1); }
else if( icase == 2 ) {
t = b(2)^2/c(2); a(2) += b(2)+t; c(2) -= t;
t = c(n-1)^2/b(n-1); a(n-1) += c(n-1)+t; b(n-1) -= t;
}
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
18
f2 = .tdma(a,b,c,d, 2,n-1); // built-in dot function ".tdma"
for.i(2,n) {
h = x(i)-x(i-1);
P[i-1]
=-f2(i-1)/(6*h)*.[1,-x(i) ]^3+(-f(i-1)/h+f2(i-1)*h/6)*.[1,-x(i)]
+f2(i) /(6*h)*.[1,-x(i-1)]^3+( f(i )/h-f2(i )*h/6)*.[1,-x(i-1)];
}
}
#> spline3;
//----------------------------------------------------------------------
// Tchebyshev interpolation
//----------------------------------------------------------------------
poly tcheby(double a,b,n, ftn(x)) {
x = y = .ones(n,1);
for.k(1,n) {
z = cos((n+0.5-k)*pi/n);
x(k) = a+(b-a)/2*(z+1);
y(k) = ftn(x(k));
}
return .interp(x,y); // interpolation polynomial
}
#> tcheby;
//----------------------------------------------------------------------
// Hermite interpolation
//----------------------------------------------------------------------
double hermite(xx, matrix &x,&y,&y1) {
// x : grid points
// y : y(x)
// y1 : y'(x)
k = x.ipos(xx); // (xx-x(k))*(xx-x(k+1)) < 0
if( k == 0 ) return NaN; // out of interval
h = x(k+1)-x(k);
s = (xx-x(k))/h;
a = s*s*(3-2*s);
yy = (1-a)*y(k)+a*y(k+1)+h*s*(1-s)*( (1-s)*y1(k)-s*y1(k+1) );
return yy;
}
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
19
#> hermite;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 6 Differentiation and Integration
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//----------------------------------------------------------------------
// integration accounting for indefinite integral
//----------------------------------------------------------------------
double integ(a,b, f(x))
{
aa = a; bb = b; flip = 1;
if(a > b) { aa = b; bb = a; flip = -1; }
sum = 0.;
h = 0.05;
alpha = 1.2;
if( aa < -0.5*inf && 0.5*inf < bb ) { // -inf<x<inf
a = 0;
for[300] {
sum += int.x(a,a+h) ( f(x) ) + int.x(-a-h,-a) ( f(x) );
a += h;
h *= alpha;
}
}
else if( aa < -0.5*inf ) { // -inf<x<bb
a = bb;
for[300] {
sum += int.x(a-h,a) ( f(x) );
a -= h;
h *= alpha;
}
}
else if( 0.5*inf < bb ) { // aa<x<inf
a = aa;
for[300] {
sum += int.x(a,a+h) ( f(x) );
a += h;
h *= alpha;
}
}
else { // aa<x<bb
a = b = 0.5*(aa+bb);
h = 0.25*(bb-aa);
for[30] {
sumo = sum;
sum += int.x(a,a+h) (f(x)) + int.x(b-h,b) (f(x));
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
20
a += h; b -= h;
h *= 0.5;
if( sum.-.sumo < 1.e-8) break;
}
}
sum *= flip;
return sum; }
#> integ;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 7 Initial Value Problems
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// prototype
matrix user_ode (double t,tf,h, matrix y,fun(double t,matrix y));
matrix adaptive_ode (double t,tf,h, matrix y,fun(double t,matrix y),
double tol);
/*
//--------------------------------------------------------------------------
// sample run
//--------------------------------------------------------------------------
%> "simple example of ODE";
#> matrix fun1(double t, matrix y) = [ -y(1)-5*exp(-t)*sin(5*t) ];
#> ysol = user_ode( 0,3, 0.03, [ 1 ], fun1 );;
#> ysol.plot;
//--------------------------------------------------------------------------
// sample run for Van der Pol equation
//--------------------------------------------------------------------------
%> "stiff ODE with Van der Pol equation";
#> matrix VanderPol1(double x, matrix y) = [ y(2), 1*(1-y(1)^2)*y(2)-y(1) ];
#> ysol = adaptive_ode(0,20, 0.2, [ 2,0 ], VanderPol1, 0.01);;
#> ysol.len;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
21
// ans = 127
#> ysol.endrow;
// ans = [ 20 2.00809 -0.0469113 0.000154643 ]
#> plot( ysol.col(1), ysol.col(2));
// Van der Pol equation with
//----------------------------------------------------------------------------
#> matrix VanderPol2(double x, matrix y) = [ y(2), 10*(1-y(1)^2)*y(2)-y(1) ];
#> yans = adaptive_ode(0,60, 2, [ 2,0 ], VanderPol2, 0.01);;
#> yans.len;
// ans = 681
#> yans.endrow;
// ans = [ 60 1.801 -0.079977 2.29483e-006 ]
#> plot( yans.col(1), yans.col(2));
// Van der Pol equation with
//----------------------------------------------------------------------------
#> matrix vanderpol3(double t, matrix y) = [ y(2), 100*(1-y(1)^2)*y(2)-y(1) ];
#> ysol = adaptive_ode(0,300, 2, [ 2,0 ], vanderpol3, 0.01 );;
#> ysol.len; // number of time steps
// ans = 15053
#> ysol.endrow;
// ans = [ 300 -1.53485 0.0111001 0.000871423 ]
#> yfig = ysol.skiprow(10);; plot( yfig.col(1), yfig.col(2));
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
22
// Van der Pol equation with
*/
//==========================================================================
// user_odecoef::
//==========================================================================
double user_odecoef(double icase, matrix &A,&B,&C)
{
switch( icase ) {
case 1: // Euler = 1st RK
A = [1]; B = [0];
C = [ 0 ];
break;
case 2: // (modified Euler) predictor-corrector = 2nd RK
A = [1,1]/2; B = [0,1];
C = [ 0; 1,0 ];
break;
case 3: // polygon = 2nd RK
A = [0,1]; B = [0,1]/2;
C = [ 0; 0.5,0 ];
break;
case 4: // Ralston = 2nd RK
A = [1,2]/3; B = [0,3]/4;
C = [ 0; 0.75,0 ];
break;
case 5: // 3rd RK
A = [1,4,1]/6; B = [0,1,2]/2;
C = [ 0; 0.5; -1,2,0 ];
break;
case 6: // Runge = 4th RK
A = [1,2,2,1]/6; B = [0,1,1,2]/2;
C = [ 0; 0.5; 0,0.5; 0,0,1,0 ];
break;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
23
case 7: // Kutta = 4th RK
A = [1,3,3,1]/8; B = [0,1,2,3]/3;
C = [ 0; 1/3; -1/3,1; 1,-1,1,0 ];
break;
case 8: // Gill = 4th RK
s = 1/sqrt(2);
A = [0.5,1-s,1+s,0.5]/3; B = [0,1,1,2]/2;
C = [ 0; 0.5; -0.5+s, 1-s; 0, -s, 1+s, 0 ];
break;
case 9: // Fehlberg = 4th RK
A = [ 25/216, 0, 1408/2565, 2197/4104, -0.2 ];
B = [ 0, 0.25, 3/8, 12/13, 1 ];
C = [ 0;
0.25;
3/32, 9/32; // 3rd
1932/2197, -7200/2197, 7296/2197; // 4th
439/216, -8, 3680/513, -845/4104, 0 ]; // 5th
break;
case 10: // Fehlberg = 5th RK
A = [ 16/135, 0, 6656/12825, 28561/56430, -9/50, 2/55 ];
B = [ 0, 0.25, 3/8, 12/13, 1, 0.5 ];
C = [ 0;
0.25;
3/32, 9/32; // 3rd
1932/2197, -7200/2197, 7296/2197; // 4th
439/216, -8, 3680/513, -845/4104; // 5th
-8/27, 2, -3544/2565, 1859/4104, -11/40,0 ]; // 6th
}
return A.len; // A.len = A.length = A.longer
}
//==========================================================================
// user_odeRK::
//==========================================================================
void user_odeRK(
double to,h,
matrix &y,&yo, &A,&B,&C,&K, // ampersand & means 'refer' not 'copy'
matrix fun(double t, matrix y))
{
// to : previous time at whicvh solutions are known
// h : magnitude of time step, h = t-to
// yo : solution at previous time step
// y : dependent variables for coupled ODEs, y(1),y(2), ... , y(numeq)
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
24
// A,B,C : coefficients for integration scheme
// K : generalized slopes for integration scheme
K.row(1) = fun(to,yo); // B(1) = C.row(1) = 0
for.i(2,A.len) {
t = to + B(i)*h;
y = yo + h*( C.row(i) * K );
K.row(i) = fun(t,y);
}
y = yo + h*( A * K );
}
//==========================================================================
// user_ode:: for positive h
//==========================================================================
matrix user_ode(double t,tf,h, matrix y,fun(double t,matrix y))
{
// t : initial time
// tf : final time
// h : size of time step
// y : initial conditions, [ y(1), y(2), ... , y(n) ]
// fun : ODE in matrix form, [ y'(1)=f1, y'(2)=f2, ... , y'(n)=fn ]
icase = 9; // Fehlberg 4th, change this manually
sdim = user_odecoef(icase, A,B,C);
K = .zeros(sdim,y.len);
yo = fun(t,y);
if( yo.len != y.len ) "ode function is not valid in dimenension";
num = 0;
ysol = [ t, y ];
while(1) {
yo = y;
if( t+h >= tf ) h = tf-t ; // stay exact at the final time
user_odeRK(t,h, y,yo, A,B,C,K, fun);
t += h;
ysol _= [ t, y ]; // stack newly-obtained solutions
if( t >= tf || t.-.tf < 1.e-6 || ++num > 10000 ) break;
}
return ysol;
}
#> user_ode;
//==========================================================================
// adaptive_ode:: for positive h
//==========================================================================
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
25
matrix adaptive_ode(double t,tf,h, matrix y,fun(double t,matrix y),
double tol)
{
// t : initial time
// tf : final time
// h : size of time step
// y : initial conditions, [ y(1), y(2), ... , y(n) ]
// fun : ODE in matrix form, [ y'(1)=f1, y'(2)=f2, ... , y'(n)=fn ]
s = user_odecoef( 9, A5,B5,C5); K5 = .zeros(s,y.len); // Fehlberg 4th
s = user_odecoef(10, A6,B6,C6); K6 = .zeros(s,y.len); // Fehlberg 5th
E6 = [ 1/360, -128/4275, -2197/75240, 0, 1/50, 2/55 ];
yo = fun(t,y);
if( yo.len != y.len ) "ode function is not valid in dimenension";
num = 0;
ysol = [ t, y, 0 ];
while(1) {
yo = y;
if( t+h > tf ) h = tf-t ; // stay exact at the final time
do {
user_odeRK(t,h, y,yo, A6,B6,C6,K6, fun);
yerr = h * |(E6*K6).maxentry|; // error estimation
if( yerr > tol) h *= 0.1; // reduce h where stiff
} while( yerr > tol );
// y = yo + h*(A5 * K6..(1:5)()); // if prefered Fehlberg 4th
t += h;
ysol _= [ t, y, yerr ]; // stack newly-obtained solutions
if( yerr < tol ) h *= 1.25; // increase h where plain
if( t >= tf || t.-.tf < 1.e-6 || ++num > 100000 ) break;
if( .mod(num,1000) == 0 ) "adaptive_ode is running" ;;
}
return ysol;
}
#> adaptive_ode;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 8 Boundary Value Problems
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void bvp2nd(double a,b,nx, matrix &x,&f,&u) ;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
26
matrix DE (double x,f,u) = [ 1, 2*x, 0, 0 ]; // [ cp, cu, cf, cs ]
matrix BC1(double x,f,u) = [ 1,0,1 ]; // [ b1u, b1f, b1r ]
matrix BC2(double x,f,u) = [ 0,1,1 ]; // [ b2u, b2f, b2r ]
//----------------------------------------------------------------------
/*
#> (a,b) = (0,1); nx = 5;
#> bvp2nd(a,b,nx, x,f,u);
#> f;
#> plot(x,f);
*/
//======================================================================
// bvp2nd::
//======================================================================
void bvp2nd(double a,b,nx, matrix &x,&f,&u)
{
// 3 user-functions must be written
//matrix DE (double x,f,u) = [ cp, cu, cf, cs ]
//matrix BC1(double x,f,u) = [ b1u, b1f, b1r ]
//matrix BC2(double x,f,u) = [ b2u, b2f, b2r ]
h = (b-a)/nx;
x = (a,b).span(nx+1);
f = u = .zeros(1,nx+1);
A = B = C = R = .zeros(1,nx+1);
// boundary points are moved to 1 and nx+1 for matrix index
for.i(2,nx) { // internal points 2,3,...,nx-1,nx
c = DE(x(i),f(i),u(i)); // c = [ cp, cu, cf, cs ]
c(1) /= h^2;
c(2) /= 2*h;
A(i) = -2*c(1)+ c(3);
B(i) = c(1) - c(2);
C(i) = c(1) + c(2);
R(i) = -c(4);
}
bc = BC1(x(1),f(1),u(1)); // bc = [ b1u, b1f, b1r ]
bc(1) /= 2*h;
dn = 1 / (bc(2)-3*bc(1));
p0 = bc(3)*dn; R(2) -= B(2)*p0;
p1 = -4*bc(1)*dn; A(2) += B(2)*p1;
p2 = bc(1)*dn; C(2) += B(2)*p2;
bc = BC2(x(nx+1),f(nx+1),u(nx+1)); // bc = [ b2u, b2f, b2r ]
bc(1) /= 2*h;
[101] 020 Numerical Analysis Using M#math, www.msharpmath.com
27
dn = 1 / (bc(2)+3*bc(1));
q0 = bc(3)*dn; R(nx) -= C(nx)*q0;
q1 = 4*bc(1)*dn; A(nx) += C(nx)*q1;
q2 = -bc(1)*dn; B(nx) += C(nx)*q2;
f = .tdma(A,B,C,R, 2,nx); // dot function .tdma
f( 1) = p0 + p1*f(2) + p2*f(3);
f(nx+1) = q0 + q1*f(nx) + q2*f(nx-1);
u( 1) = ( -f(3) + 4*f(2) - 3*f(1) )/(2*h);
u(nx+1) = (f(nx-1) - 4*f(nx) + 3*f(nx+1))/(2*h);
for.i(2,nx) u(i) = (f(i+1)-f(i-1))/(2*h);
}
#> bvp2nd;
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 9 Eigenvalue Problems
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Chapter 10 Coupled Equations and Minimum Searching
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++