Solving a system with two equations and two variables in a for loop - matlab

I would like to solve a system with two equations and two variables.
Tau(i)and Roh(i) are input arrays.
Tau=[0.91411 0.91433 0.91389 0.91399 0.91511 0.915]
Roh=[0.07941 0.07942 0.07952 0.07946 0.07951 0.07947]
I would like to calculate R(i)and t(i)for each istep (for loop).
I will be glad to have help to solve the equations.
Tau(i)-((1-R(i))^2*t(i))/(1-R(i)^2*t(i)^2)==0
Roh(i)-R(i)-((1-R(i))^2*R(i)*t(i)^2)/(1-R(i)^2*t(i)^2)==0
I have tried the following script but I have difficulty to write the proper code to export the data. I get only "sym" which is not a value.
function [R,t] = glassair(Tau, Roh)
for i=1:6
syms R(i) t(i)
eq1(i)=sym('Tau(i)-((1-R(i))^2*t(i))/(1-R(i)^2*t(i)^2)');
eq2(i)=sym('Roh(i)-R(i)-((1-R(i))^2*R(i)*t(i)^2)/(1-R(i)^2*t(i)^2)');
sol(i)=solve(eq1(i),R(i), eq2(i),t(i));
end
end

There where multiple issues with your code.
Using the R(i) syntax with variables, you mixed in symbolic functions. I think here you only have variables. Same with eq(i), this created a symbolic function, not a list of your equations (as you probably intended)
You called solve with the wrong order of arguments
You called solve with the wrong order of arguments
Passing a string to sym your known constants Tau and Roh where not substituted, you ended up with 4 unknowns in your equations
.
Tau=[0.91411 0.91433 0.91389 0.91399 0.91511 0.915]
Roh=[0.07941 0.07942 0.07952 0.07946 0.07951 0.07947]
syms R t
for i=1:6
eq1=Tau(i)-((1-R)^2*t)/(1-R^2*t^2);
eq2=Roh(i)-R-((1-R)^2*R*t^2)/(1-R^2*t^2);
sol=solve([eq1,eq2]);
allsol(i).R=double(sol.R);
allsol(i).t=double(sol.t);
end

You just need to define the functions once, then use a for loop to get the values.
function [R_out,t_out] = glassair(Tau_in, Roh_in)
syms R t Tau Roh
eq1 = Tau-((1-R)^2*t)/(1-R^2*t^2);
eq2 = Roh-R-((1-R)^2*R*t^2)/(1-R^2*t^2);
R_out = zeros(1,6); % Given it will be always 6
t_out = zeros(1,6);
for i=1:6
Tau = Tau_in(i);
Roh = Roh_in(i);
sol = solve( subs( [eq1;eq2] ) );
R_out(i) = double(sol.R);
t_out(i) = double(sol.t);
end
end
Matlab is very smart in that defines the types for you. When you solve the equations it detects which variables are needed. The zero allocation is for speed up.

Related

Newton Raphson method problem when iterating a variable

I need help with a problem. I written a program to calculate the value of a function using the Newton Raphson method. However, the function also has a variable i would like to iterate over, V. The program runs fine until the second iteration of the outer for loop, then the inner for loop will not run further once it reaches the Newton Raphson function. If someone has any ideas of what is wrong, I would greatly appreciate it. The error i get is: Warning: Solution does not exist because the system is inconsistent.
The code is below for detail.
for V = 1:50;
syms x;
f(V)= Il-x-Is.*(exp((q.*(V+x.*Rs))./(1000.*y.*K.*T))-1)-((V+x.*Rs)./Rsh);
g(V)=diff(f(V));
x0 = 0;
i = 1;
for i=1:10
f0=vpa(subs(f,x,x0));
f0_der=vpa(subs(g,x,x0));
y=x0-f0/f0_der; % Newton Raphson
x0=y;
end
end
Assuming you have a function defined like
func = #(x,V) V+x+exp(x);
There are plenty of options that avoid expensive symbolic calculations.
Firstly, making a vector of values of x0 using fzero and a for loop:
for V = 1:50
x0(V) = fzero(#(x) func(x,V),0);
end
Secondly, the same thing again but written as an anonymous function, so you can call x0(1.5) or x0(1:50):
x0 = #(V) arrayfun(#(s) fzero(#(x) func(x,s),0),V);
Finally, if you want to use ten steps of Newton's method and calculate the derivative symbolically (although this is not a great method),
syms y Vsym
g = matlabFunction(diff(func(y,Vsym),y),'Vars',[y Vsym]);
for V = 1:50
x0(V) = 0;
for i = 1:10
x0(V) = x0(V)-func(x0(V),V)/g(x0(V),V); % Newton Raphson
end
end
Which at least will be more efficient in the loops because it's just using anonymous functions.

How to find argmin/best fit/optimize for an overdetermined quadratic system for multiple variables in Matlab

I have 100 equations with 5 variables. Is there a function in Matlab which I can use to find the optimal solution of these equations?
My problem is to find argmin ||(a-ic)^2 + (b-jd)^2 + e - h(i,j)|| over all i, j from -10 to 10. ie.
%% Note: not Matlab code. Just showing the Math.
for i = -10:10
for j = -10:10
(a-ic)^2 + (b-jd)^2 + e = h(i,j)
known: h(i,j) is a 10*10 matrix,and i,j are indexes
expected: the optimal result of a,b,c,d,e
You can try using lsqnonlin as follows.
%% define a helper function in your .m file
function f = fun(x)
a=x(1); b=x(2); c=x(3); d=x(4); e=x(5); % Using variable names from your question. In other situations, be careful when overwriting e.
f=zeros(21*21,0); % size(f) is taken from your question. You should make this a variable for good practice.
for i = -10:10
for j = -10:10
f(10*(i+10+1)+(j+10+1)) = (a-i*c)^2 + (b-j*d)^2 + e - h(i,j); % 10 is taken from your question.
end
end
end
(Aside, why is your h(i,j) taking negative indices??)
In your main function you can simply write
function out=myproblem(x0)
out=lsqnonlin(#fun,x0);
end
In your cmd, you can call with specific initial try such as
myproblem([0,0,0,0,0])
Helper function over anonymous because in my experience helpers get sped up by JIT while anonymous do not. I also opted to reshape in the loops as an opposed to actually call reshape after because I expect reshape to cost significant extra time. Remember that O(1) in fun is not O(1) in lsqnonlin.
(As always, a solution to a nonlinear problem is not guaranteed.)

Solving a system of ODEs in MATLAB?

this is my first time posting, so if you need anymore info or I havn't done something correct please let me know!
I want to plot a system of ODES, which would be no problem as I would do the following;
F=#(t,x) [
.the RHS of my first order ODES.
];
[t x]=ode45(F,[Range], [Initial conditions]);
Where a vector would be created containing x'(1), x'(2),... where x(1), x(2) would be the time dependant variable.
However my system is a little more complicated. I have 6 differential equations which are made up of equations that include differential equations and the time dependant variables. For example, the RHS of my ODES are something like
2*x(2)*x'(1)*f(a)
Where f(a) could be another function based on constants, a.
I have set up my code in the following order;
Constants, then equations of the form f(a), then my differential equations followed by the ode45 solver and the plot commands. However I am getting several errors "Undefined function or variable" as early equations depend on variables/equations that are not defined until later.
Thank you ever so much for you help :)
As suggested, here an example of the type of my code;
`%Constants
a=34
b=31
c=20
%Equations
A=b*cos(2*pi)
B=a*EQ1
C=c*x(2)
%DifferentialEquations
EQ1=x(1)*A
EQ2=(EQ3-EQ1)*(B-C)
EQ3=x(2)*x(3)
F=#(t,x) [EQ1;EQ2;EQ3;];[t x]=ode45(F,[0 10], [0 0 0 ]);
Provides the error.
Produces the undefined function or variable 'DEQ1A'.
Based on the comment you are trying to use a variable before it is defined. In MATLAB you need to define your variables and functions before you use them. Because the equations are functions of each other you can use anonymous functions to define F.
Example:
a=34;
b=31;
c=20;
A = b*cos(2*pi);
EQ1 = #(x) x(1)*A;
B = #(x) a*EQ1(x);
C = #(x) c*x(2);
EQ3 = #(x) x(2)*x(3);
EQ2 = #(x) (EQ3(x) - EQ1(x))*(B(x)-C(x));
F = #(t,x) [EQ1(x);EQ2(x);EQ3(x)];
[t,x] = ode45(F,[0 10], [0 0 0]);

How to solve multiple non-linear and independent equations in MATLAB

I have 16 non-linear equations which are independent of each other i.e. they are not a system of equations. One way is to create 16 separate sub-routines and use fsolve to solve which i generally do.
But i need to reduce the number of sub-routines from 16 to one. Let me try to give an example of what i'm doing so far:
u01 = .001;....u016 = .001;
options=optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-,'TolFun',1e-6,'MaxIter',10^5);
u1 = fsolve(#polsim1,u01,options);
..
..
u16 = fsolve(#polsim16,u016,options);
So, in the above example i have 16 subroutines i.e. polsim1-polsim16 where each includes 1 non-linear equation to solve for u's. This method is very cumbersome and messy. I need to do that in one subroutine. I believe i need to use index n = 1 to 16. But i'm not sure how to use it and where to use it.
Just create an array of functions and initial guesses, as shown in the first example of the documentation for fsolve.
% Array of equations, nx1 in size for n equations.
% Ensure that the input (x) is indexed in each equation, e.g. x(1) in eqn 1
polsim = #(x) [x(1).^2 - 1
2*x(2) + 3];
% Array of initial guesses, corresponding element-wise to eqn array
u0 = [0.01; 0.01];
% Solver options
options = optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-5,'TolFun',1e-6,'MaxIter',10^5);
% Solve
u = fsolve(F, u0, options);
>> u = [1.000; -1.500] % As expected for the equations in F and intial guesses
You should rewrite your code to use vectors/cell arrays as follows:
% Write the initial point as a vector
u0(1) = .001;
..
u0(16) = .001;
% Write the equations as a cell array
polsim{1} = #polsim1;
..
polsim{16} = #polsim16;
options=optimset('Display','notify','MaxFunEvals',10^7,'TolX',1e-1,'TolFun',1e-6,'MaxIter',10^5);
u = zeros(u0); % Allocate output space for efficiency
% loop over all the equations
for i=1:length(u0)
u(i) = fzero(polsim{i},u0(i),options);
end
Note that I used fzero instead of fsolve to improve the efficiency, see this post for more information.
Trick to automatically construct vector/cell array (Deprecated)
For completeness, I should mention that you can initialise u0 and polsim automatically using eval:
for i=1:16
eval(['u0(', num2str(i), ') = u0', num2str(i),';']);
eval(['polsim{', num2str(i), '} = polsim', num2str(i),';']);
end
Note that I do not recommend this method. It is much better to directly define them as a vector/cell array.

Implementing iterative solution of integral equation in Matlab

We have an equation similar to the Fredholm integral equation of second kind.
To solve this equation we have been given an iterative solution that is guaranteed to converge for our specific equation. Now our only problem consists in implementing this iterative prodedure in MATLAB.
For now, the problematic part of our code looks like this:
function delta = delta(x,a,P,H,E,c,c0,w)
delt = #(x)delta_a(x,a,P,H,E,c0,w);
for i=1:500
delt = #(x)delt(x) - 1/E.*integral(#(xi)((c(1)-c(2)*delt(xi))*ms(xi,x,a,P,H,w)),0,a-0.001);
end
delta=delt;
end
delta_a is a function of x, and represent the initial value of the iteration. ms is a function of x and xi.
As you might see we want delt to depend on both x (before the integral) and xi (inside of the integral) in the iteration. Unfortunately this way of writing the code (with the function handle) does not give us a numerical value, as we wish. We can't either write delt as two different functions, one of x and one of xi, since xi is not defined (until integral defines it). So, how can we make sure that delt depends on xi inside of the integral, and still get a numerical value out of the iteration?
Do any of you have any suggestions to how we might solve this?
Using numerical integration
Explanation of the input parameters: x is a vector of numerical values, all the rest are constants. A problem with my code is that the input parameter x is not being used (I guess this means that x is being treated as a symbol).
It looks like you can do a nesting of anonymous functions in MATLAB:
f =
#(x)2*x
>> ff = #(x) f(f(x))
ff =
#(x)f(f(x))
>> ff(2)
ans =
8
>> f = ff;
>> f(2)
ans =
8
Also it is possible to rebind the pointers to the functions.
Thus, you can set up your iteration like
delta_old = #(x) delta_a(x)
for i=1:500
delta_new = #(x) delta_old(x) - integral(#(xi),delta_old(xi))
delta_old = delta_new
end
plus the inclusion of your parameters...
You may want to consider to solve a discretized version of your problem.
Let K be the matrix which discretizes your Fredholm kernel k(t,s), e.g.
K(i,j) = int_a^b K(x_i, s) l_j(s) ds
where l_j(s) is, for instance, the j-th lagrange interpolant associated to the interpolation nodes (x_i) = x_1,x_2,...,x_n.
Then, solving your Picard iterations is as simple as doing
phi_n+1 = f + K*phi_n
i.e.
for i = 1:N
phi = f + K*phi
end
where phi_n and f are the nodal values of phi and f on the (x_i).