How to use Equations in Matlab? - matlab

I'm working on Matlab Code for Lagrange Interpolation.
My problem is working with equations.
For solving Lagrange you need to find the Li(x)'s ( L0(x) to Ln(x) ) first:
e.g. for L0(x) we've got:
L0(x) = (x-x1) (x-x2) (x-x3) / (x0-x1) (x0-x2) (x0-x3)
which for an example it would be:
l0(x) = ( x^3 - ( 2 * x^2 ) + 2x ) / 6
which is an equation.
I write the code but it won't accept the variable z (which i used instead of X ) and it tells:
"Undefined function or variable 'z'."
Which is certainly correct cause it's a variable and not a data but how could i use or write this?

MATLAB by default does not like undefined variables (as do most programming languages!)
You have two ways of solving your problem: numerically solving Lagrange "by hand" -- i.e. with functions like ode45, or trying to do it symbolically. This means that you either have to explicitly define x as a symbolic variable -- with syms x and use the symbolic maths toolbox, or, alternatively, use a numerical scheme and something like ode45.
If you want to define a function in MATLAB, you need to plonk a definition into a separate file and save it.
For example:
function out = ellZero( x, a )
x0 = a(1); x1 = a(2); x2 = a(3); x3 = a(4); % SET Constants
out = (x-x1).*(x-x2).*(x-x3)./((x0-x1).*(x0-x2).*(x0-x3)); % RET Expression
end
If you want to learn more about how MATLAB handles functions and 'sub-functions', have a look at the documentation. You might also be interested in the Partial Differential Equation Toolbox.
Hope that helps!

Related

How can vector elements with indexing be used in a MATLAB symbolic expression?

I would like to create a MATLAB function with vector inputs. The problem is that the inputs of a function created by matlabFunction() has only scalar inputs.
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
matlabFunction(f,'file','testFunction.m');
matlabFunction(f,'file','testFunction.m','vars',[x,y]); % tried with different options but doesn't work
This is the result (with x1,x2,y1,y2 inputs instead of x,y):
function f = testFunction(x1,x2,y1,y2)
%TESTFUNCTION
% F = TESTFUNCTION(X1,X2,Y1,Y2)
% This function was generated by the Symbolic Math Toolbox version 8.2.
% 10-Apr-2019 21:28:40
f = x1+x2+y1+y2;
Is there a solution to this problem within MATLAB? Or do I need to write a program opening the file as txt and replacing the words...
Update: I managed to solve the problem. For me, the best solution is the odeToVectorField() function.
Manually it is more difficult to give vector inputs to a function created by matlabFunction(). One way is the following:
syms y;
f=str2sym('y(1)+y(2)');
matlabFunction(f,'File','fFunction','Vars',y);
With this method, you need to manipulate the equation as a string (which is possible but not practical...), then re-convert it to symbolic expression.
If you check the result of f=x(1)+x(2)+y(1)+y(2) you will see that it is also scalar. Do simple test:
x = sym('x',[2 1]);
y = sym('y',[2 1]);
f=x(1)+x(2)+y(1)+y(2);
disp(f)
The results is x1 + x2 + y1 + y2. So there's nothing wrong with your matlabFunction expression, it just save what you give. If you need it to be stored in the form x(1)+x(2)+y(1)+y(2) you need to rewrite your f expression so it will be stored in vector form, until passing it to matlabFunction. Or alternatively you can create your file structure manualy using fprintf, look docs.

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

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.

Solving an ODE when the function is given as discrete values -matlab-

I have the following ODE:
x_dot = 3*x.^0.5-2*x.^1.5 % (Equation 1)
I am using ode45 to solve it. My solution is given as a vector of dim(k x 1) (usually k = 41, which is given by the tspan).
On the other hand, I have made a model that approximates the model from (1), but in order to compare how accurate this second model is, I want to solve it (solve the second ODE) by means of ode45. My problem is that this second ode is given discrete:
x_dot = f(x) % (Equation 2)
f is discrete and not a continuous function like in (1). The values I have for f are:
0.5644
0.6473
0.7258
0.7999
0.8697
0.9353
0.9967
1.0540
1.1072
1.1564
1.2016
1.2429
1.2803
1.3138
1.3435
1.3695
1.3917
1.4102
1.4250
1.4362
1.4438
1.4477
1.4482
1.4450
1.4384
1.4283
1.4147
1.3977
1.3773
1.3535
1.3263
1.2957
1.2618
1.2246
1.1841
1.1403
1.0932
1.0429
0.9893
0.9325
0.8725
What I want now is to solve this second ode using ode45. Hopefully I will get a solution very similar that the one from (1). How can I solve a discrete ode applying ode45? Is it possible to use ode45? Otherwise I can use Runge-Kutta but I want to be fair comparing the two methods, which means that I have to solve them by the same way.
You can use interp1 to create an interpolated lookup table function:
fx = [0.5644 0.6473 0.7258 0.7999 0.8697 0.9353 0.9967 1.0540 1.1072 1.1564 ...
1.2016 1.2429 1.2803 1.3138 1.3435 1.3695 1.3917 1.4102 1.4250 1.4362 ...
1.4438 1.4477 1.4482 1.4450 1.4384 1.4283 1.4147 1.3977 1.3773 1.3535 ...
1.3263 1.2957 1.2618 1.2246 1.1841 1.1403 1.0932 1.0429 0.9893 0.9325 0.8725];
x = 0:0.25:10
f = #(xq)interp1(x,fx,xq);
Then you should be able to use ode45 as normal:
tspan = [0 1];
x0 = 2;
xout = ode45(#(t,x)f(x),tspan,x0);
Note that you did not specify what values of of x your function (fx here) is evaluated over so I chose zero to ten. You'll also not want to use the copy-and-pasted values from the command window of course because they only have four decimal places of accuracy. Also, note that because ode45 required the inputs t and then x, I created a separate anonymous function using f, but f can created with an unused t input if desired.

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).

How do I make a function from a symbolic expression in MATLAB?

How can I make a function from a symbolic expression? For example, I have the following:
syms beta
n1,n2,m,aa= Constants
u = sqrt(n2-beta^2);
w = sqrt(beta^2-n1);
a = tan(u)/w+tanh(w)/u;
b = tanh(u)/w;
f = (a+b)*cos(aa*u+m*pi)+a-b*sin(aa*u+m*pi); %# The main expression
If I want to use f in a special program to find its zeroes, how can I convert f to a function? Or, what should I do to find the zeroes of f and such nested expressions?
You have a couple of options...
Option #1: Automatically generate a function
If you have version 4.9 (R2007b+) or later of the Symbolic Toolbox you can convert a symbolic expression to an anonymous function or a function M-file using the matlabFunction function. An example from the documentation:
>> syms x y
>> r = sqrt(x^2 + y^2);
>> ht = matlabFunction(sin(r)/r)
ht =
#(x,y)sin(sqrt(x.^2+y.^2)).*1./sqrt(x.^2+y.^2)
Option #2: Generate a function by hand
Since you've already written a set of symbolic equations, you can simply cut and paste part of that code into a function. Here's what your above example would look like:
function output = f(beta,n1,n2,m,aa)
u = sqrt(n2-beta.^2);
w = sqrt(beta.^2-n1);
a = tan(u)./w+tanh(w)./u;
b = tanh(u)./w;
output = (a+b).*cos(aa.*u+m.*pi)+(a-b).*sin(aa.*u+m.*pi);
end
When calling this function f you have to input the values of beta and the 4 constants and it will return the result of evaluating your main expression.
NOTE: Since you also mentioned wanting to find zeroes of f, you could try using the SOLVE function on your symbolic equation:
zeroValues = solve(f,'beta');
Someone has tagged this question with Matlab so I'll assume that you are concerned with solving the equation with Matlab. If you have a copy of the Matlab Symbolic toolbox you should be able to solve it directly as a previous respondent has suggested.
If not, then I suggest you write a Matlab m-file to evaluate your function f(). The pseudo-code you're already written will translate almost directly into lines of Matlab. As I read it your function f() is a function only of the variable beta since you indicate that n1,n2,m and a are all constants. I suggest that you plot the values of f(beta) for a range of values. The graph will indicate where the 0s of the function are and you can easily code up a bisection or similar algorithm to give you their values to your desired degree of accuracy.
If you broad intention is to have numeric values of certain symbolic expressions you have, for example, you have a larger program that generates symbolic expressions and you want to use these expression for numeric purposes, you can simply evaluate them using 'eval'. If their parameters have numeric values in the workspace, just use eval on your expression. For example,
syms beta
%n1,n2,m,aa= Constants
% values to exemplify
n1 = 1; n2 = 3; m = 1; aa = 5;
u = sqrt(n2-beta^2);
w = sqrt(beta^2-n1);
a = tan(u)/w+tanh(w)/u;
b = tanh(u)/w;
f = (a+b)*cos(aa*u+m*pi)+a-b*sin(aa*u+m*pi); %# The main expression
If beta has a value
beta = 1.5;
eval(beta)
This will calculate the value of f for a particular beta. Using it as a function. This solution will suit you in the scenario of using automatically generated symbolic expressions and will be interesting for fast testing with them. If you are writing a program to find zeros, it will be enough using eval(f) when you have to evaluate the function. When using a Matlab function to find zeros using anonymous function will be better, but you can also wrap the eval(f) inside a m-file.
If you're interested with just the answer for this specific equation, Try Wolfram Alpha, which will give you answers like:
alt text http://www4c.wolframalpha.com/Calculate/MSP/MSP642199013hbefb463a9000051gi6f4heeebfa7f?MSPStoreType=image/gif&s=15
If you want to solve this type of equation programatically, you probably need to use some software packages for symbolic algebra, like SymPy for python.
quoting the official documentation:
>>> from sympy import I, solve
>>> from sympy.abc import x, y
Solve a polynomial equation:
>>> solve(x**4-1, x)
[1, -1, -I, I]
Solve a linear system:
>>> solve((x+5*y-2, -3*x+6*y-15), x, y)
{x: -3, y: 1}