-
Notifications
You must be signed in to change notification settings - Fork 0
/
ivpnl1_.m
74 lines (72 loc) · 1.97 KB
/
ivpnl1_.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
function [ps,qs,k] = ivpnl1_(f,dfdu,ps,qs,ss,J,K,E1,E2,Ea1,Ea2 ...
,kmax,tol)
%IVPNL1_ Computational kernel for first-order nonlinear IVPs.
%
% [PS,QS,K] = IVPNL1_(F,DFDU,PS,QS,SS,J,K,E1,E2,EA1,EA2,KMAX,TOL) solves
%
% U'(T) = F(T,U(T)), U(A) = UA.
%
% Inputs:
%
% F: right-hand side of the differential equation
%
% DFDU: derivative of F(T,U) with respect to U
%
% PS: sample of a starting guess PSTART(T) on a grid TS of degree M+1
%
% QS: sample of P' on a grid TS_ of degree M
%
% SS: degree-M grid of collocation nodes
%
% J: net-change matrix for the grid TS
%
% K: truncated integration matrix for the grid TS_
%
% E1: matrix for resampling from TS to SS
%
% E2: matrix for resampling from TS_ to SS
%
% EA1: matrix for evaluating at T = A from a sample on TS
%
% EA2: matrix for evaluating at T = A from a sample on TS_
%
% KMAX: maximum number of Newton steps
%
% TOL: tolerance for termination criterion
%
% Outputs:
%
% PS: sample of the collocation solution P(T) on TS
%
% QS: sample of the collocation solution derivative P'(T) on TS_
%
% K: number of Newton steps before convergence, or [] in case of
% failure
%
% This is an internal routine called by IVPNL1GEN, IVPNL1UNI, and
% IVPNL1CHEB.
%
% Copyright 2019 Brian Sutton
m = length(qs)-1;
% iterate
for k = 1:kmax
ps_ = E1*ps;
fs = arrayfun(f,ss,ps_);
% terminate if solution found
if all(qs==fs), return; end
% take a Newton step
dfdus = arrayfun(dfdu,ss,ps_);
[dps,dqs] = ivpl1_(-dfdus,ones(m+1,1),fs-qs,[1 0],0 ...
,J,K,E1,E2,Ea1,Ea2);
ps = ps+dps;
qs = qs+dqs;
% signal failure on NaN or infinity
if any(~isfinite(ps))||any(~isfinite(qs))
k = []; return;
end
% terminate on numerical convergence
de = tol*max([max(abs(ps)) max(abs(qs)) 1]);
if max([ max(abs(dps)) max(abs(dqs)) ])<=de, return; end
end
% signal failure to converge
k = [];