Using Adams-Bashforth method in Matlab to solve Lorenz-System Equation - matlab

I am trying to use my second order Adams-Bashforth function here:
function [t,x] = Adams(f,t_max,x0,N)
h = t_max/N;
t = linspace(0,t_max,N+1);
x = zeros(2,N+1);
x(:,1) = x0;
x(:,2) = x0 + h.*(f(t(1),x(:,1)));
for i=2:N
x(:,i+1) = x(:,i) + h.*((3/2.*f(t(i),x(:,i))-(1/2).*f(t(i-1),x(:,i-1))));
end
end
In order to solve the Lorenz System Equation. However, whenever I try to call the function, I get an error.
sigma = 10;
beta = 8/3;
rho = 28;
f = #(t,a) [-sigma*a(1) + sigma*a(2); rho*a(1) - a(2) - a(1)*a(3); -beta*a(3) + a(1)*a(2)];
[t,a] = Adams(f,10,[1 1 1],100);
plot3(a(:,1),a(:,2),a(:,3))
Output:
"Unable to perform assignment because
the size of the left side is 2-by-1 and
the size of the right side is 1-by-3.
Error in Project>Adams (line 55)
x(:,1) = x0;"
Is the issue with my function, or with how I am calling my function? Any help would be appreciated.

in line 5 of your Adams function: x(:,1) = x0;
the input x0 is the initial conditions [1 1 1] a row vector of size [3x1], but x is an array of size zeros(2,N+1), or [2x101].
There are several mistakes here, the first you assign a row vector to a colon vector, not only that, but the size of the container in that first column of array x which is [2x1] , that is a different size than the size of x0. that is what the error tells you.
The function is buggy there , and it wont work unless you debug it according to the original intent of that method you are trying to implement.
note that also in the script f=#(t,... is expected to have an input t, but there is not t in the expression [-sigma*a(1) + sigma*a(2); rho*a(1) - a(2) - a(1)*a(3); -beta*a(3) + a(1)*a(2)];

Related

Problem with separating Real and Imaginary parts for fmincon (constrained MATLAB optimization). How to program it correctly?

I am trying to solve this optimization problem with fmincon function in MATLAB:
Where all H are complex matrices, g and Pdes are complex column vectors, D0 and E0 are numbers.
I expect to get complex column vector of g (and in general its should be complex), So I divided problem in two parts: real and imag, but it does not work, MATLAB returning me a message:
Not enough input arguments.
Error in temp>nonlincon (line 17)
c(1) = norm ( H_d*([g(1)+1i*g(4); g(2)+1i*g(5); g(3)+1i*g(6)]) )^2 - D_0;
Error in temp (line 12)
= fmincon(objective,x0,[],[],[],[],[],[],nonlincon);
Where I am wrong?
And in general am I right in writing given problem in the following way:?
% For example:
D_0 = 2*10^(-5)*10^(60/10);
E_0 = 50;
H_b = rand(15,3) + 1i*rand(15,3);
P_des = rand(15,1) + 1i*rand(15,1);
H_d = rand(10,3) + 1i*rand(10,3);
objective = #(g) (norm ( H_b*([g(1)+1i*g(4); g(2)+1i*g(5); g(3)+1i*g(6)]) - P_des ))^2;
x0 = ones(1,3*2)';
options = optimoptions('fmincon','MaxFunctionEvaluations',10e3);
[X,FVAL,EXITFLAG,OUTPUT,LAMBDA,GRAD,HESSIAN]...
= fmincon(objective,x0,[],[],[],[],[],[],nonlincon);
% So I expect to get a column vector g: 1st 3 elements - Real part, next 3 - Imag
function [c,ceq] = nonlincon(g, H_d, E_0, D_0)
c(1) = (norm ( H_d*([g(1)+1i*g(4); g(2)+1i*g(5); g(3)+1i*g(6)]) ))^2 - D_0;
c(2) = (norm ([g(1)+1i*g(4); g(2)+1i*g(5); g(3)+1i*g(6)]))^2 - E_0;
ceq = [];
end
You just need to specify that nonlincon is a function of variable g only when calling fmincon
The code is as follow
[X,FVAL,EXITFLAG,OUTPUT,LAMBDA,GRAD,HESSIAN]...
= fmincon(objective,x0,[],[],[],[],[],[],#(g)nonlincon(g, H_d, E_0, D_0));
Solution X
X = [0.2982; 0.1427; 0.3597; -0.0729; -0.1187; 0.2090]

How to increase number in range set till it gives a specific answer?

I've wrote a rungekutta code and there is a specific x range that it should calculate up to it. The problem is that the prof. wants a code that keeps on adding up by itself till it reaches the required answer.
I tried using the 'if' function but it only works once and no more (thus, even creating a mismatch in array lengths.
Code:
h=0.5;% step size
z=0.5;
x = 0:h:z;% the range of x
y = zeros(1,length(x));
y(1) = 50;% initial condition
F_xy = #(t,x) (37.5-3.5*x);%function
for i=1:(length(x)-1)% calculation loop
k_1 = F_xy(x(i),y(i));
k_2 = F_xy(x(i)+h,y(i)+h*k_1);
y(i+1) = y(i) + (h/2)*(k_1+k_2);% main equation
if y(i+1)>11
x=0:h:z+1;
end
end
disp (y(i+1))
Error of arrays length (shows that if function only works once)
41.4063
Error using plot
Vectors must be the same length.
Error in code6rungekutta2ndorder (line 30)
plot(x,y), grid on
it should keep on increasing by +1 in the 'z' variable till the answer of y(i+1) is less than 11. (correct z should be 9.5)
As #medicine_man suggested, you need a while loop:
h=0.5;% step size
z=0.5;
x = 0;
y = 50;% initial condition
F_xy = #(t,x) (37.5-3.5*x);%function
m = 0;
while y(m+1) > 11
m = m+1;
x = x+h;
k_1 = F_xy(x,y(m));
k_2 = F_xy(x+h,y(m)+h*k_1);
y(m+1) = y(m) + (h/2)*(k_1+k_2);% main equation
end
figure;
plot(0:h:x, y);
Your terminate condition, which is y(m+1) > 11, is checked at the beginning of each iteration of the while loop. In the loop, you can increment the value of x and update your y array. The loop runs until the terminate condition is met.
The result of the above code:

Use Matlab/Maple to find roots of a nonlinear equation

I am having difficulty in finding roots of a nonlinear equation. I have tried Matlab and Maple both, and both give me the same error which is
Error, (in RootFinding:-NextZero) can only handle isolated zeros
The equation goes like
-100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H)
The variable is H in the equation.
How do I find the roots (or the approximate roots) of this equation?
Matlab Code:
The function file:
function hor_force = horizontal(XY, XZ, Lo, EAo, qc, VA)
syms H
equation = (-1*ZZ) + (H/qc)*(cosh((qc/H)*(XZ- XB))) - H/qc + ZB;
hor_force = `solve(equation);`
The main file:
EAo = 7.5*10^7;
Lo = 100.17;
VA = 2002;
XY = 0;
ZY = 0;
XB = 50;
ZB = -2;
XZ = 100;
ZZ = 0;
ql = 40;
Error which Matlab shows:
Error using sym/solve (line 22)
Error using maplemex
Error, (in RootFinding:-NextZero) can only handle isolated zeros
Error in horizontal (line 8)
hor_force = solve(equation);
Error in main (line 34)
h = horizontal(XY, XZ, Lo, EAo, ql, VA)
http://postimg.org/image/gm93z3b7z/
You don't need the symbolic toolbox for this:
First, create an anonymous function that can take vectors at input (use .* and ./:
equation = #(H) ((-1*ZZ) + (H./qc).*(cosh((qc./H).*(XZ- XB))) - H./qc + ZB);
Second, create a vector that you afterwards insert into the equation to find approximately when the sign of the function changes. In the end, use fzero with x0 as the second input parameter.
H = linspace(1,1e6,1e4);
x0 = H(find(diff(sign(equation(H))))); %// Approximation of when the line crosses zero
x = fzero(equation, x0) %// Use fzero to find the crossing point, using the initial guess x0
x =
2.5013e+04
equation(x)
ans =
0
To verify:
You might want to check out this question for more information about how to find roots of non-polynomials.
In Maple, using the expression from your question,
restart:
ee := -100 + 0.1335600000e-5*H + (1/20)*H*arcsinh(2003.40/H):
Student:-Calculus1:-Roots(ee, -1e6..1e6);
[ 5 ]
[-1.240222868 10 , -21763.54830, 18502.23816]
#plot(ee, H=-1e6..1e6, view=-1..1);

Create flexible function handle

I am using numerical integration in MATLAB, with one varibale to integrate over but the function also contains a variable number of terms depending on the dimension of my data. Right now this looks like the following for the 2-dimensional case:
for t = 1:T
fxt = #(u) exp(-0.5*(x(t,1)-theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x(t,2) -theta*norminv(u,0,1)).^2);
f(t) = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3);
end
I would like to have this function flexible in the sense that there could be any number of data points in, each in the following term:
exp(-0.5*(x(t,i) -theta*norminv(u,0,1)).^2);
I hope this is understandable.
If x and u have a valid dimension match (vector-vector or array-scalar) for the subtraction, you can put the whole matrix x into the handle and pass it to the integral function using the name-parameter pair ('ArrayValued',true):
fxt = #(u) exp(-0.5*(x - theta*norminv(u,0,1)).^2) .* ...
exp(-0.5*(x - theta*norminv(u,0,1)).^2);
f = integral(fxt,1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
[Documentation]
You may need a loop if integral ever passes a vector u into the handle.
But in looking at how the integral function is written, the integration nodes are entered as scalars for array-valued functions, so the loop shouldn't be necessary unless some weird dimension-mismatch error is thrown.
Array-Valued Output
In response to the comments below, you could try this function handle:
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
Then your current loop would look like
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
for t = 1:T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
end
The ArrayValued flag is needed since x and u will have a dimension mismatch.
In this form, another loop would be needed to sweep through the k indexes.
However, we can improve this function by skipping the loop altogether since each iterate of the loop is independent by using the ArrayValued mode:
fx = #(u,k) prod(exp(-0.5*(x(:,1:k)-theta*norminv(u,0,1)).^2),2);
k = 2;
f = integral(#(u)fx(u,k),1e-4,1-1e-4,'AbsTol',1e-3,'ArrayValued',true);
Vector-Valued Output
If ArrayValued is not desired, which may be the case if the integration requires a lot of subdivisions and a vector-valued u is preferable, you can also try a recursive version of the handle using cell arrays:
% x has size [T,K]
fx = cell(K,1);
fx{1} = #(u,t) exp(-0.5*(x(t,1) - theta*norminv(u,0,1)).^2);
for k = 2:K
fx{k} = #(u,t) fx{k-1}(u,t).*exp(-0.5*(x(t,k) - theta*norminv(u,0,1)).^2);
end
f(T) = 0;
k = 2;
for t = 1:T
f(t) = integral(#(u)fx{k}(u,t),1e-4,1-1e-4,'AbsTol',1e-3);
end
ThanksTroy but now I run into the follwing:
x = [0.3,0.8;1.5,-0.7];
T = size(x,1);
k = size(x,2);
theta= 1;
fx = #(u,t,k) prod(exp(-0.5*(x(t,1:k) - theta*norminv(u,0,1))^2));
for t = 1,T
f(t) = integral(#(u)fx(u,t,k),1e-4,1-1e-4,'AbsTol',1e-3);
end
Error using -
Matrix dimensions must agree.
Error in #(u,t,k)prod(exp(-0.5*(x(t,1:k)-theta*norminv(u,0,1))^2))
Error in #(u)fx(u,t,k)
Error in integralCalc/iterateScalarValued (line 314)
fx = FUN(t);
Error in integralCalc/vadapt (line 133)
[q,errbnd] = iterateScalarValued(u,tinterval,pathlen);
Error in integralCalc (line 76)
[q,errbnd] = vadapt(#AtoBInvTransform,interval);
Error in integral (line 89)
Q = integralCalc(fun,a,b,opstruct);

Sending a function into a matlab function

I'm trying build a matlab function that will evaluate a function and vector that are sent in as parameters. I'm having a hard time trying to figure out how to send in the function so that it can be evaluated in the matlab function. I figured out how to do it without the function but I'm a little lost trying to evaluate it within a matlab function. Below is my code...
This is what I'm trying to do...
x = [x1 x2]';
f = x(x1)^2 + 2 * (x2)^2
x = [5 10];
f = (5)^2 + 2 * (10)^2 % which I would like to return 225, not a column vector
This is what I have and what I have tried...
x = [5 10]';
% without using a matlab function
% k = 1
% f = x(k)^2 + 2 * x(k + 1)^2; % returns the correct answer of 225
f = x^2 + 2 * x^2 % complains about the scalar 2
f = x.^2 + 2 * x.^2 % returns a column vector [75; 300]
function [value] = evalFunction(f,x)
value = f(x);
I've tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(#f,x) %Error: "f" was previously used as a variable
So I tried...
f = #(x) x.^2 + 2 * (x+1).^2;
value = evalFunction(f,x) %value = [97;342]
I'm new to matlab so any help is appreciated. I've been doing some research and found some stuff here on stackoverflow but can't seem to get it to work. I've seen there are other ways to do this, but I will eventually be adding more code to the matlab evalFunction function so I'd like to do it this way. Thanks!
Anonymous functions and function handles plus array indexing. Taking x as a 2-element vector, define and use your function like:
f = #(x) x(1).^2 + 2 * x(2).^2;
value = evalFunction(f,x) % but you can just do f(x) if that is all you need
However, if evalFunction does nothing other than evaluate f at x, then you don't need it at all. Just do f(x).
Alternately,
f = #(x1,x2) x1.^2 + 2*x2.^2;
value = evalFunction(f,x1,x2); % here your function will call it by f(x1,x2)
You are probably coming at this from a C background - in Matlab, x+1 is the entire vector x with 1 added - not the element offset by 1.
The function you need is
f = #(x)x(1).^2 + 2 * (x(2)).^2;
or, to be a little more "matlab-like":
f = #(x) [1 2] * x(1:2)'.^2;
Which performs the element-wise square of the first two elements of x as a column vector, and then does the matrix multiplication with [1 2], resulting in
1 * x(1) .^2 + 2 * x(2) .^2;
Which seems to be what you were asking for.
caveat: did not have opportunity to test this...