Figure 2.27:

Stability regions for Adams predictor-corrector methods; \dot {x}=\lambda x.

Code for Figure 2.27

Text of the GNU GPL.

main.m


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
% Program to plot stability plots for predictor-corrector methods

% A linear multistep formula is: x+ = G(w) x  with w = a*Delta t
% for differential equation xdot = ax with stepsize Delta t
%
% The eigenvalues of G determine the stability of the method;
% The method is absolutely stable iff max (abs( eig G(w))) < 1

% We find the value of w s.t. z = exp(i*theta) is an eigenvalue
% of G for theta in [0, 2*pi].  Actually, [0, 4*pi] to cover entire
% curve in w.

% We demonstrate here stability curve for APC2, APC3 and APC4 methods.
% NOTE: APCn uses an n-1st order predictor and nth order corrector
%

% Setting grid points

% pass parameters to function, jbr, 6/28/2018

axisbox = [-1.5 1.5 -1 1];
xa = axisbox(1); xb = axisbox(2); ya = axisbox(3); yb = axisbox(4);
nhalf  = 50;
npts = 2*nhalf+1;
theta = linspace(0, 4*pi, npts);
lamvec = exp(i*theta);

% predictor coefficients, 1st, 2nd, 3rd, 4th order
p{1} = [1, 0, 0, 0];
p{2} = [3/2, -1/2, 0, 0];
p{3} = [23/12, -4/3, 5/12, 0];
p{4} = 1/24*[55, -59, 37, -9];
% corrector coefficients, 1st, 2nd, 3rd, 4th order
c = cell(4);
c{1} = [1, 0, 0, 0];
c{2} = [1/2, 1/2, 0, 0];
c{3} = 1/12*[5, 8, -1, 0];
c{4} = 1/24*[9, 19, -5, 1];

par = struct();
par.p = p; par.c = c;


PCsvec = [2,3,4];
npcs = length(PCsvec);
wsol(1:npcs) = {zeros(npts,1)};
%optimset("ComplexEqn", "on");
for j = 1:npcs
  PCs = PCsvec(j);
  par.PCs = PCs;
  w0 = 0 + 0*i;
  for k = 1:length(theta)
    lam = lamvec(k);
    par.lam = lam;
    [w,fval,info] = fsolve(@(w) characteristic(w, par), w0);
    if (info <= 0 )
      j, k, info, w, w0
    end
    w0 = w;
    wsol{j}(k) = w;
  end
end

% check for intersecting loops
for ind = 1:npcs
  for k = 1: length(wsol{ind})-1
    z = [real(wsol{ind})'; imag(wsol{ind})'];
    iloop = 0;
    for j = k+2 : length(wsol{ind})-1
      % find first place where z(k) intersects the rest of the path
      lam = inv([z(:,k)-z(:,k+1), z(:,j+1)-z(:,j)])*(z(:,j+1)-z(:,k+1));
      if (lam >=0 & lam <=1)
	iloop = k+1:j;
	zint = lam(1)*z(:,k)+(1-lam(1))*z(:,k+1);
	break
      end
    end
    if (iloop ~= 0)
      % chop out wsol(iloop) and replace with single interpolated value zint
      zcp = complex(zint(1),zint(2));
      wsol{ind}(iloop(1)) = zcp;
      iloop(1) = [];
      wsol{ind}(iloop) = [];
    end
  end
end

figure()
hold on
for j = 1:npcs
  plot(real(wsol{j}), imag(wsol{j}),'-o')
end
%axis (axisbox)

% rewrite real and imaginary parts for plotting
store = cell(npcs,1);
for k = 1: npcs
  tmp = cell2mat(wsol(k));
  store(k) = {[real(tmp), imag(tmp)]};
end
save ("APC_stability.dat", "store")

characteristic.m


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function retval = characteristic(w, par)
  % note, the predictor order is one less than corrector
  cc = par.c{par.PCs}; pp=par.p{par.PCs-1};
      a(1) = 1 + w*( cc(1)*(1+w*pp(1)) + cc(2) );
      a(2) = w*( cc(1)*w*pp(2) + cc(3) );
      a(3) = w*( cc(1)*w*pp(3) + cc(4) );
      a(4) = w*cc(1)*w*pp(4);
  order = length(a);
  G = [a; eye(order-1), zeros(order-1,1)]-par.lam*eye(order);
  retval = det(G);