Why is exponential integrator method giving poor results? - matlab

//u' + Au = g(t,u) can be solved by exponential integrators also
//Following snippet is for exp INtegrators
A = -full(Strang(11))
A[end,1]=1;A[1,end]=1;
g(t,u) = 2-u
u0 = zeros(11);u0[6]=1
nsteps = 1000
tmax = 10.0
h = tmax/nsteps
u = u0
t = 0
for k in 1:nsteps
u = expm(-h*A)*u + h*((expm(-h*A)-1)\(-h*A))*g(t,u)
t = k*h
end
//this is for euler's method
for k in 1:nsteps
u += h*(A*u + h*g(t,u))
t = k*h
end
Why are they giving poor results?
The method is exploding very badly, it should converge to [1.99]*11 , or something like that?
Is there any mistake while implementing Exp Integrator?

The test problem is a singular matrix. A better test is the setup:
using SpecialMatrices
A = -full(Strang(11))
g(t,u) = 2-u
u = zeros(11);u[6]=1
nsteps = 10000
tmax = 1.0
h = tmax/nsteps
t = 0
Using this, fix the h in the Euler to get (notice there's an extra h, my bad:
u = zeros(11);u[6]=1
for k in 1:nsteps
u += h*(A*u + g(t,u))
t = k*h
end
#show u
u = [0.93573,1.19361,1.26091,1.29627,1.34313,1.37767,1.34313,1.29627,1.26091,1.19361,0.93573]
But to find out what's wrong, start looking at numbers. What happens A=0? Well, we know that phi(z) = (e^z - 1)/z. By L'Hopital's rule, phi(z) -> 1 as z->0. Therefore, in order for our implementation to have the same behavior, we have to have that same result. But let's check what happens:
expm(zeros(5,5))
5×5 Array{Float64,2}:
1.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0
0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 1.0
Notice that this gives the identity matrix. So think about the limit: if the bottom is going to zero... how can this be constant? We must have that the top is going to zero... so the top is going to I.
And that's the moment of clarity: the author meant 1 in the field that you're in. So for a matrix input, 1=I. When you realize that, you fix the code:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = expm(h*A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
#show u
u = [0.935722,1.1936,1.26091,1.29627,1.34313,1.37768,1.34313,1.29627,1.26091,1.1936,0.935722]
Moral of the story: for programming mathematics, you also have to debug your math.
Edit
Get a more efficient form one step at a time. First, try and force another varphi term:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = (I + A*(expm(h*A)-I)/A)*u + ((expm(h*A)-I)/A)*g(t,u)
t = k*h
end
#show u
Now gather:
# Norsett-Euler
u = zeros(11);u[6]=1
for k in 1:nsteps
u = u + ((expm(h*A)-I)/A)*(A*u + g(t,u))
t = k*h
end
#show u
This is the efficient form of the method you were trying to write. Then you can cache the operator since A is constant:
# Norsett-Euler
u = zeros(11);u[6]=1
phi1 = ((expm(h*A)-I)/A)
for k in 1:nsteps
u = u + phi1*(A*u + g(t,u))
t = k*h
end
#show u

The exponential Euler-Rosenbrock step should be for u'=Lu+g(t,u)
u = expm(h*L)*u + ((expm(h*L)-1)/L)*g(t,u)
Note that the inverted matrix is L (in Matlab A/B == A*inv(B) and A\B == inv(A)*B), and there is no naked h in the formula. In your case, L = -A.
An alternative method to split off the exponential part has is as follows. Set u(t) = exp(-t*A)*v(t) which translates into the differential equation
exp(-t*A)*v'(t) = g(t,exp(-t*A)*v((t))
Now apply the forward Euler step for v
v(t+h) = v(t) + h * exp(t*A)*g(t,exp(-t*A)*v((t))
which translated back into terms in u gives
u(t+h) = exp(-(t+h)*A)*v(t+h)
= exp(-h*A) * ( u(t) + h * g(t,u(t)) )
This should equally result in a first order method.

Related

How to get the upper limit of a integration?

I have a probability distribution function which is the following:
f = #(x) h0 * (1/sqrt(2*pi*sig2)) .* exp(-(x-mh0).^2 / (2*sig2))+ (1-h0) * (1/sqrt(2*pi*sig2)) .* exp(-(x-mh1).^2 / (2*sig2));
I am doing this Matlab. Other than x, everything is constant.
The range for this function is (-4 , 8). I would like to divide this area into equal mass i.e. 1/10 ( 10 intervals, each with mass 1/10).
I am thinking about integrating it and check the upper limit as know the result of the integration. But I didn't find a way to do this?
Can anyone please help me with this?
Thanks in advance
A simple bisection search will find the splitting point simply if you're not worried about ultimate efficiency. E.g., to split in two:
sig2 = rand;
mh0 = rand;
h0 = rand;
mh1 = rand;
f = #(x) h0 * (1/sqrt(2*pi*sig2)) .* exp(-(x-mh0).^2 / (2*sig2))+ (1-h0) * (1/sqrt(2*pi*sig2)) .* exp(-(x-mh1).^2 / (2*sig2));
l = -4;
u = 8;
fprintf('total integral = %e\n', quad(f, l, u));
l0 = l;
u0 = u;
while u0 - l0 > 0.0001
m = 0.5 * (l0 + u0);
w = quad(f, l, m);
if w > 0.5
u0 = m;
else
l0 = m;
end
end
m = 0.5 * (l0 + u0);
fprintf('integral to %e = %e\n', m, quad(f, l, m));
To split into 10 parts, recurse on the subparts. First split at 0.5, then split the low interval at 0.2, then split the low part of that at 0.1, and the upper part at 0.3, and then the 0.3/0.5 interval to get 0.4. Similarly for the upper parts.

Stochastic differential equation with callback in Julia

I'm trying to solve a diffusion problem with reflecting boundaries, using various SDE integrators from DifferentialEquations.jl. I thought I could use the FunctionCallingCallback to handle the boundaries, by reflecting the solution about the domain boundaries after every integrator step.
This is my code
using DifferentialEquations
K0 = 1e-3
K1 = 5e-3
alpha = 0.5
K(z) = K0 + z*K1*exp(-z*alpha)
dKdz(z) = K1*exp(-alpha*z) - K1*alpha*z*exp(-alpha*z)
a(z,p,t) = dKdz(z)
b(z,p,t) = sqrt(2*K(z))
dt = 0.1
tspan = (0.0,1.0)
z0 = 1.0
prob = SDEProblem(a,b,z0,tspan)
function reflect(z, p, t, integrator)
bottom = 2.0
if z < 0
# Reflect from surface
z = -z
elseif z > bottom
# Reflect from bottom
z = 2*bottom - z
end
return z
end
cb = FunctionCallingCallback(reflect;
func_everystep = true,
func_start = true,
tdir=1)
sol = solve(prob, EM(), dt = dt, callback = cb)
Edit: After solving my initial problem thanks to the comment by Chris Rackauckas, I modified my reflect function. Now the code runs, but the solution contains negative values, which should have been prevented by reflection about 0 after every step.
Any ideas as to what's going wrong here would be greatly appreciated.
Note by the way that the FunctionCallingCallback example found here contains two different function signatures for the callback function, but I get the same problem with both. It's also not clear to me if the callback should modify the value of z in place, or return the new value.
Edit 2:
Based on Chris Rackauckas' answer, and looking at this example, I've modified by reflect function thus:
function reflect(z, t, integrator)
bottom = 2.0
if integrator.u < 0
# Reflect from surface
integrator.u = -integrator.u
elseif integrator.u > bottom
# Reflect from bottom
integrator.u = 2*bottom - integrator.u
end
# Not sure if the return statement is required
return integrator.u
end
Running this with initial condition z0 = -0.1 produces the following output:
retcode: Success
Interpolation: 1st order linear
t: 11-element Array{Float64,1}:
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
1.0
u: 11-element Array{Float64,1}:
-0.1
-0.08855333388147717
0.09862543518953905
0.09412012313587219
0.11409372573454478
0.10316400521980074
0.06491042188420941
0.045042097789392624
0.040565317051189105
0.06787136817395374
0.055880083559589955
It seems to me that what's happening here is:
The first output value is just z0. I expected the reflection to be applied first, given that I set func_start = true.
The second value also being negative indicates two things:
The callback was not called prior to the first integrator call.
The callback was not called prior to storing the output after the first integrator call.
I would have expected all the values in the output to be positive (i.e., have the callback applied to them before storing the output). Am I doing something wrong, or should I simply adjust my expectations?
The FunctionCallingCallback is a function (u,t,integrator), so I'm not sure how your code didn't error for you. It should be:
using DifferentialEquations
K0 = 1e-3
K1 = 5e-3
alpha = 0.5
K(z) = K0 + z*K1*exp(-z*alpha)
dKdz(z) = K1*exp(-alpha*z) - K1*alpha*z*exp(-alpha*z)
a(z,p,t) = dKdz(z)
b(z,p,t) = sqrt(2*K(z))
dt = 0.1
tspan = (0.0,1.0)
z0 = 1.0
prob = SDEProblem(a,b,z0,tspan)
function reflect(z, t, integrator)
bottom = 2.0
if z < 0
# Reflect from surface
z = -z
elseif z > bottom
# Reflect from bottom
z = 2*bottom - z
end
return z
end
cb = FunctionCallingCallback(reflect;
func_everystep = true,
func_start = true,
tdir=1)
sol = solve(prob, EM(), dt = dt, callback = cb)
Edit
You don't want the function calling callback. Just use the normal callback:
using DifferentialEquations
K0 = 1e-3
K1 = 5e-3
alpha = 0.5
K(z) = K0 + z*K1*exp(-z*alpha)
dKdz(z) = K1*exp(-alpha*z) - K1*alpha*z*exp(-alpha*z)
a(z,p,t) = dKdz(z)
b(z,p,t) = sqrt(2*K(z))
dt = 0.1
tspan = (0.0,1.0)
z0 = 1.0
prob = SDEProblem(a,b,z0,tspan)
condition(u,t,integrator) = true
function affect!(integrator)
bottom = 2.0
if integrator.u < 0
# Reflect from surface
integrator.u = -integrator.u
elseif integrator.u > bottom
# Reflect from bottom
integrator.u = 2*bottom - integrator.u
end
end
cb = DiscreteCallback(condition,affect!;save_positions=(false,false))
sol = solve(prob, EM(), dt = dt, callback = cb)

Matlab : On filter() function behaving differently

I want to implement a Moving AVerage model of lag 2 whose functional form is :
y[n] = h1*x[n] + h2*x[n-1] + h3*x[n-2]
having coefficients, h_true = [h1, h2, h3];
The output is a scalar valued number at n.
Matlab has filter() function which can be used to implement a MA or AR model. But, the output is different when I implemented the equation as it is and when using the filter() function. What is the correct way? Please find below the code.
N = 10;
x = rand(1,N);
h_true = [1, 0.6, 0.3]; %h1 = 1, h2 = 0.6; h3 = 0.3
y(1) = 0.0;
y(2) = 0.0;
for i =3 : N
y(i) = h_true(1)*x(i) + h_true(2)*x(i-1) + h_true(3)*x(i-2);
end
filtered_y = filter(h_true,1,x);
y and filtered_y is different
While some of the terms do vanish for i<3, not all terms actually do. So as you compute y, you should still be accounting for those non vanishing terms:
y(1) = h_true(1)*x(1);
y(2) = h_true(1)*x(2) + h_true(2)*x(1);
for i =3 : N
y(i) = h_true(1)*x(i) + h_true(2)*x(i-1) + h_true(3)*x(i-2);
end

Performing closed loop system response using lsim using matlab

I'm trying to replicate the step response of a certain system using the lsim function however the resulting output isn't quite right. Is there anything I'm doing wrong?
Here's a comparison of my codes:
USING STEP():
s = tf('s');
G = 56.54/(0.12*s^2+0.6*s+58.31);
D = 0.21 + 19.95/s + 0.04*s;
H = G*D/(1+G*D);
y = 2.5*step(H);
plot(y)
USING LSIM():
ya = 0;
e = 2.5;
t1 = 0:.05:10;
er = 2.5*ones(length(t1),1);
G = 56.54/(0.12*s^2+0.6*s+58.31);
D = 0.21 + 19.95/s + 0.04*s;
GDss = ss(D*G);
x = [0 0 0];
for k = 1:100
[y,t,x] = lsim(GDss,er,t1,x);
ya(k) = y(length(t1));
er = (e - y(length(t1)))*ones(length(t1),1);
x = x(98:100);
end
plot(ya)
Plots y and ya "should" be the same but it's not what's coming up.
Help?
As far as I can see, you are calculating the step response of H = G*D/(1+G*D); with "step()", but calculating the step response of GDss = D*G; with "lsim()". Since the systems are not the same, the results will not be the same either.
As Captain Future mentioned, you are not checking equivalent things. And of course because of that the open loop system is unstable and blows up.
However for such things do it a bit more structured for your own sake and also lsim already does that for loop for you.
H = minreal(feedback(series(D,G),1));
opt = stepDataOptions('StepAmplitude',2.5);
step(H,1,opt)
%
t = 0:0.01:1;
u = ones(1,length(t));
figure,lsim(H,u,t)

Manually changing RGB to HSI matlab

I would like to preface this by saying, I know some functions, including RGB2HSI could do this for me, but I would like to do it manually for a deeper understanding.
So my goal here is to change my RGB image to HSI color scheme. The image is in .raw format, and i am using the following formulas on the binary code to try and convert it.
theta = arccos((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S = 1 - 3./(R + G + B)
I = 1/3 * (R + G + B)
if B <= G H = theta if B > G H = 360 - theta
So far I have tried two different things, that have resulted in two different errors. The first attempted was the following,
for iii = 1:196608
C(iii) = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S(iii) = 1 - 3./(R + G + B);
I(iii) = 1/3 * (R + G + B);
end
Now in attempting this I knew it was grossly inefficent, but I wanted to see if it was a viable option. It was not, and the computer ran out of memory and refused to even run it.
My second attempt was this
fid = fopen('color.raw');
R = fread(fid,512*384*3,'uint8', 2);
fseek(fid, 1, 'bof');
G = fread(fid, 512*384*3, 'uint8', 2);
fseek(fid, 2, 'bof');
B = fread(fid, 512*384*3, 'uint8', 2);
fclose(fid);
R = reshape(R, [512 384]);
G = reshape(G, [512 384]);
B = reshape(B, [512 384]);
C = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
S = 1 - 3./(R + G + B);
I = 1/3 * (R + G + B);
if B <= G
H = B;
if B > G
H = 360 - B;
end
end
H = H/360;
figure(1);
imagesc(H * S * I)
There were several issues with this that I need help with. First of all, the matrix 'C' has different dimensions than S and I so multiplication is impossible, so my first question is, how would I call up each pixel so I could perform the operations on them individually to avoid this dilemma.
Secondly the if loops refused to work, if I put them after "imagesc" nothing would happen, and if i put them before "imagesc" then the computer would not recognize what variable H was. Where is the correct placement of the ends?
Normally, the matrix 'C' have same dimensions as S and I because:
C = acosd((.5*(R-G) + (R-B))/((R-G).^2 + (R-B).*(G-B)).^.5);
should be
C = acosd((.5*(R-G) + (R-B))./((R-G).^2 + (R-B).*(G-B)).^.5);
elementwise division in the middle was missing . Another point is:
if B <= G
H = B;
if B > G
H = 360 - B;
end
end
should be
H = zeros(size(B));
H(find(B <= G)) = B(find(B <= G));
H(find(B > G)) = 360 - B(find(B > G));