Skip to content

Commit 2cc4c9e

Browse files
authored
Add files via upload
0 parents  commit 2cc4c9e

File tree

8 files changed

+301
-0
lines changed

8 files changed

+301
-0
lines changed

BVP.m

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
function [err]=BVP(N)
2+
3+
% solve boundary value problems using PS methods
4+
% ode: x''-tx'-x=0
5+
% BCs: x(-1)=x(1)=1
6+
%sol : exp((t^2-1)/2)
7+
8+
import casadi.*
9+
10+
%N=10;
11+
Nx=1;
12+
t0=-1;
13+
tf=1;
14+
15+
opti=casadi.Opti();
16+
17+
X=opti.variable(Nx,N+1);
18+
19+
20+
%LGL grid points and quadrature weights
21+
[tau,wi]=legslb(N+1);
22+
tau=tau';
23+
wi=wi';
24+
% differentiation matrix
25+
D=legslbdiff(N+1,tau);
26+
27+
28+
t=(tf-t0)/2*tau+(tf+t0)/2;
29+
30+
Xd=2/(tf-t0)*(D*X')';
31+
Xdd=2/(tf-t0)*(D*Xd')';
32+
33+
res=Xdd-t.*Xd-X;
34+
35+
opti.minimize(0)
36+
opti.subject_to(res(2:end-1)==0)
37+
opti.subject_to(X(1)==1)
38+
opti.subject_to(X(N+1)==1)
39+
40+
opti.set_initial(X,zeros(Nx,N+1))
41+
42+
opti.solver('ipopt')
43+
sol=opti.solve();
44+
45+
46+
Xs=sol.value(X);
47+
Xa=exp((t.^2-1)/2);
48+
%plot(t,Xs,'d',t,Xa);
49+
%xlabel('time [s]')
50+
%ylabel('$x(t)$')
51+
%figure
52+
%semilogx((abs(Xs-Xa)));
53+
%xlabel('time [s]')
54+
%ylabel('Error')
55+
56+
err=norm(Xs-Xa,2,'fro')
57+
end

IVP.m

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
% solve boundary value problems using PS methods
2+
% ode: x''-tx'-x=0
3+
%sol : exp((t^2-1)/2)
4+
5+
import casadi.*
6+
7+
N=100;
8+
Nx=1;
9+
t0=-1;
10+
tf=1;
11+
12+
opti=casadi.Opti();
13+
14+
X=opti.variable(Nx,N+1);
15+
16+
17+
%LGL grid points and quadrature weights
18+
[tau,wi]=legslb(N+1);
19+
tau=tau';
20+
wi=wi';
21+
% differentiation matrix
22+
D=legslbdiff(N+1,tau);
23+
24+
25+
t=(tf-t0)/2*tau+(tf+t0)/2;
26+
27+
Xd=2/(tf-t0)*(D*X')';
28+
Xdd=2/(tf-t0)*(D*Xd')';
29+
30+
res=Xdd-t.*Xd-X;
31+
32+
opti.minimize(0)
33+
opti.subject_to(res(2:end-1)==0)
34+
opti.subject_to(X(1)==1)
35+
opti.subject_to(X(N+1)==1)
36+
37+
opti.set_initial(X,zeros(Nx,N+1))
38+
39+
opti.solver('ipopt')
40+
sol=opti.solve();
41+
42+
43+
Xs=sol.value(X);
44+
Xa=exp((t.^2-1)/2);
45+
plot(t,Xs,'d',t,Xa);
46+
xlabel('time [s]')
47+
ylabel('$x(t)$')
48+
figure
49+
semilogx((abs(Xs-Xa)));
50+
xlabel('time [s]')
51+
ylabel('Error')
52+

README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Solving boundary value problems using pseudospectral method
2+
3+
## Requirements
4+
5+
## Problem description
6+
7+
Consider the following boundary value problem from [^1] in equation 1 and its boundary conditione are provided in equation 2.
8+
9+
$$
10+
\begin{equation}
11+
\ddot{x}-t\dot{x}-x=0
12+
\end{equation}
13+
$$
14+
15+
$$
16+
\begin{equation}
17+
x(t=-1)=x(t=1)=1
18+
\end{equation}
19+
$$
20+
21+
22+
## Analytical solution
23+
24+
The system has the analytical solution $$ x(t)=\exp{\frac{t^2-1)}{2}} $$.
25+
26+
## Numerical solution
27+
28+
In order to solve the system numerically, the problem is discretized using pseudospectral method. $$x(t)$$ is approximated using a global polynomial whose values are defined at the LGL collocation nodes. This polynomial is differentiated to the required degree and constraints are imposed. These include the boundary conditions and the satisfaction of the dynamics at the collocation points. Satifying the BC and dynamics at -1 and 1 leads to a overdetermined system. Hence, the BC are only imposed at the end points and dynamics constraints are ignored. This leads to a system of equation with equal number of variables and equations. This can lead a linear/nonlinear system of equation which can be solved.
29+
30+
## Implementation
31+
32+
In the code, the boundary conditions and the dynamics are treated as nonlinear constraints by solver "IPOPT" and the objective it set to 0.
33+
34+
## Results
35+
36+
The numerical and analytical solution are identical as shown in the figure below. In addition, the spectral convergence of the method is also additional verified by increasing the grid size progressively.
37+
38+
39+
## References
40+
41+
[^1] Wang, L. L., Samson, M. D., & Zhao, X. (2014). A well-conditioned collocation method using a pseudospectral integration matrix. SIAM Journal on Scientific Computing, 36(3), A907-A929.
42+
43+
44+
45+

convergence.m

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
clear
2+
3+
N=5:1:20;
4+
E=zeros(1,length(N));
5+
6+
for i=1:length(N)
7+
E(i)=BVP(N(i));
8+
end
9+
10+
semilogy(N,E)
11+
xlabel('grid size [N]')
12+
ylabel('discretization error')

legslb.m

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function [varargout]=legslb(n)
2+
3+
% x=legslb(n) returns n Legendre-Gauss-Lobatto points with x(1)=-1, x(n)=1
4+
% [x,w]= legslb(n) returns n Legendre-Gauss-Lobatto points and weights
5+
% Newton iteration method is used for computing nodes
6+
% See Page 99 of the book: J. Shen, T. Tang and L. Wang, Spectral Methods:
7+
% Algorithms, Analysis and Applications, Springer Series in Compuational
8+
% Mathematics, 41, Springer, 2011.
9+
% Use the function: lepoly()
10+
% Last modified on August 30, 2011
11+
12+
% Compute the initial guess of the interior LGL points
13+
nn=n-1; thetak=(4*[1:nn]-1)*pi/(4*nn+2);
14+
sigmak=-(1-(nn-1)/(8*nn^3)-(39-28./sin(thetak).^2)/(384*nn^4)).*cos(thetak);
15+
ze=(sigmak(1:nn-1)+sigmak(2:nn))/2;
16+
ep=eps*10; % error tolerance for stopping iteration
17+
ze1=ze+ep+1;
18+
19+
while max(abs(ze1-ze))>=ep, % Newton's iteration procedure
20+
ze1=ze;
21+
[dy,y]=lepoly(nn,ze);
22+
ze=ze-(1-ze.*ze).*dy./(2*ze.*dy-nn*(nn+1)*y); % see Page 99 of the book
23+
end; % around 6 iterations are required for n=100
24+
varargout{1}=[-1,ze,1]';
25+
if nargout==1, return; end;
26+
27+
% Use the weight expression (3.188) to compute the weights
28+
varargout{2}=[2/(nn*(nn+1)),2./(nn*(nn+1)*y.^2),2/(nn*(nn+1))]';
29+
30+
31+
32+

legslbdiff.m

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
% D=legslbdiff(n,x) returns the first-order differentiation matrix of size
2+
% n by n, associated with the Legendre-Gauss-Lobatto points x, which may be computed by
3+
% x=legslb(n) or x=legslbndm(n). Note: x(1)=-1 and x(n)=1.
4+
% See Page 110 of the book: J. Shen, T. Tang and L. Wang, Spectral Methods:
5+
% Algorithms, Analysis and Applications, Springer Series in Compuational
6+
% Mathematics, 41, Springer, 2011.
7+
% Use the function: lepoly()
8+
% Last modified on August 31, 2011
9+
10+
function D=legslbdiff(n,x)
11+
if n==0, D=[]; return; end;
12+
xx=x;y=lepoly(n-1,xx); nx=size(x);
13+
if nx(2)>nx(1), y=y'; xx=x'; end; %% y is a column vector of L_{n-1}(x_k)
14+
D=(xx./y)*y'-(1./y)*(xx.*y)'; %% compute L_{n-1}(x_j) (x_k-x_j)/L_{n-1}(x_k);
15+
% 1/d_{kj} for k not= j (see (3.203))
16+
D=D+eye(n); % add the identity matrix so that 1./D can be operated
17+
D=1./D;
18+
D=D-eye(n); D(1,1)=-n*(n-1)/4; D(n,n)=-D(1,1); %update the diagonal entries
19+
return;
20+

lepoly.m

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
function [varargout]=lepoly(n,x)
2+
3+
% lepoly Legendre polynomial of degree n
4+
% y=lepoly(n,x) is the Legendre polynomial
5+
% The degree should be a nonnegative integer
6+
% The argument x should be on the closed interval [-1,1];
7+
% [dy,y]=lepoly(n,x) also returns the values of 1st-order
8+
% derivative of the Legendre polynomial stored in dy
9+
% Last modified on August 30, 2011
10+
% Verified with the chart in http://keisan.casio.com/has10/SpecExec.cgi
11+
12+
if nargout==1,
13+
if n==0, varargout{1}=ones(size(x)); return; end;
14+
if n==1, varargout{1}=x; return; end;
15+
polylst=ones(size(x)); poly=x; % L_0(x)=1, L_1(x)=x
16+
for k=2:n, % Three-term recurrence relation:
17+
polyn=((2*k-1)*x.*poly-(k-1)*polylst)/k; % kL_k(x)=(2k-1)xL_{k-1}(x)-(k-1)L_{k-2}(x)
18+
polylst=poly; poly=polyn;
19+
end;
20+
varargout{1}=polyn;
21+
end;
22+
23+
if nargout==2,
24+
if n==0, varargout{2}=ones(size(x)); varargout{1}=zeros(size(x)); return;end;
25+
if n==1, varargout{2}=x; varargout{1}=ones(size(x)); return; end;
26+
27+
polylst=ones(size(x)); pderlst=zeros(size(x));poly=x; pder=ones(size(x));
28+
% L_0=1, L_0'=0, L_1=x, L_1'=1
29+
for k=2:n, % Three-term recurrence relation:
30+
polyn=((2*k-1)*x.*poly-(k-1)*polylst)/k; % kL_k(x)=(2k-1)xL_{k-1}(x)-(k-1)L_{k-2}(x)
31+
pdern=pderlst+(2*k-1)*poly; % L_k'(x)=L_{k-2}'(x)+(2k-1)L_{k-1}(x)
32+
polylst=poly; poly=polyn;
33+
pderlst=pder; pder=pdern;
34+
end;
35+
varargout{2}=polyn; varargout{1}=pdern;
36+
end;
37+
38+
return
39+

lepolym.m

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
function [varargout]=lepolym(n,x)
2+
3+
% lepolym Legendre polynomials of degree up to n, i.e., 0,1, ...,n
4+
% y=lepolym(n,x) returns the Legendre polynomials
5+
% The degree should be a nonnegative integer
6+
% The argument x is a vector be on the closed interval [-1,1];
7+
% [dy,y]=lepolym(n,x) also returns the values of 1st-order
8+
% derivatives of the Legendre polynomials upto n stored in dy
9+
% Note: y (and likewise for dy) saves L_0(x), L_1(x), ...., L_n(x) by rows
10+
% i.e., L_k(x) is the (k+1)th row of the matrix y (or dy)
11+
% Last modified on August 30, 2011
12+
13+
dim=size(x); xx=x; if dim(1)>dim(2), xx=xx'; end; % xx is a row-vector
14+
if nargout==1,
15+
if n==0, varargout{1}=ones(size(xx)); return; end;
16+
if n==1, varargout{1}=[ones(size(xx));xx]; return; end;
17+
polylst=ones(size(xx)); poly=xx; % L_0(x)=1, L_1(x)=x
18+
y=[polylst;poly];
19+
for k=2:n, % Three-term recurrence relation:
20+
polyn=((2*k-1)*xx.*poly-(k-1)*polylst)/k; % kL_k(x)=(2k-1)xL_{k-1}(x)-(k-1)L_{k-2}(x)
21+
polylst=poly; poly=polyn; y=[y;polyn];
22+
end;
23+
varargout{1}=y;
24+
end;
25+
26+
if nargout==2,
27+
if n==0, varargout{2}=ones(size(xx)); varargout{1}=zeros(size(xx)); return;end;
28+
if n==1, varargout{2}=[ones(size(xx));xx];
29+
varargout{1}=[zeros(size(xx));ones(size(xx))]; return; end;
30+
31+
polylst=ones(size(xx)); pderlst=zeros(size(xx));poly=xx; pder=ones(size(xx));
32+
y=[polylst;poly]; dy=[pderlst;pder];
33+
% L_0=1, L_0'=0, L_1=x, L_1'=1
34+
for k=2:n, % Three-term recurrence relation:
35+
polyn=((2*k-1)*xx.*poly-(k-1)*polylst)/k; % kL_k(x)=(2k-1)xL_{k-1}(x)-(k-1)L_{k-2}(x)
36+
pdern=pderlst+(2*k-1)*poly; % L_k'(x)=L_{k-2}'(x)+(2k-1)L_{k-1}(x)
37+
polylst=poly; poly=polyn; y=[y;polyn];
38+
pderlst=pder; pder=pdern; dy=[dy;pdern];
39+
end;
40+
varargout{2}=y; varargout{1}=dy;
41+
end;
42+
43+
return
44+

0 commit comments

Comments
 (0)