I use this code in Maple:
Ur := unapply(simplify(subs(r = r/a^(1/2), z = z/a, ur0(r, z))/a^(1/2)), r, z)
I obtain this result:
Is there a way for Maple to understand that diff(p(r/sqrt(a)),r/sqrt(a)) = 1/sqrt(a)*diff(p(r),r)?
To be able to differentiate with regards to an algebraic expression you can use the algsubs command together with the inert Diff command and then subs back the expression if the function is differentiable.
Diff(p(r/sqrt(a)),r/sqrt(a)); # Equation
algsubs(r/sqrt(a) = x,%); # Substitute derivative variable (1)
p:=x -> x^2; # Define function to differentiate
value(%%); # Evaluate the differential (1)
subs(x=r/sqrt(a),%); # Substitute back in again
Related
I would like to solve the following polynomial numerically for r:
I am trying to use fzero() as follows:
r = (5/(r^2*9))- ((2)/(9*(6-r)^2))
x0 = 10; % some initial point
x = fzero(r,x0)
How can this be done with fzero()?
Input variable and function name should be different
Just change the function name to pol
To use fzero the function pol have to be a function handle
defined via #
pol =#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2))
x0 = 10; % some initial point
x = fzero(pol,x0)
solution
x = 3.6754
It should be noted that, the first argument in fzero() should be "a function handle, inline function, or string containing the name of the function to evaluate", but yours is just an expression, which is not valid.
Besides the approach by #Adam (using function handle), another way is to use anonymous function, i.e.,
x = fzero(#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2)) ,x0)
where
#(r) (5/(r^2*9))- ((2)/(9*(6-r)^2))
is the anonymous function with respect to argument r.
You will get the same result that x = 3.6754.
I have a non-linear equation with a constant 'X'.
I want to obtain the solution of the equation for 10 different values of 'X'.
What is the best way of doing it in MATLAB?
Employing fsolve, I thought of doing this using a loop which runs 10 times. But the problem is that it's not possible to send value of 'X' as a parameter to the function which is called by fsolve (as according to its syntax, fsolve can send only the initial guess value) and which contains the non-linear equation.
This is my MATLAB code:
function f = crd(m)
X=0.1; %Paramter for whose different values I want to solve the NLE using a loop
t=(1/(0.8/3600))*log(1/(1-X));
U=350; P=0.1134; T=165; L=21.415; %Constants
a=0.00102*820*2200/(U*P); %Constant
Q=(0.8/3600)*900*exp(-(0.8/3600)*t)*0.9964*(347.3*1000);
Tmi=60; %Constant
b=m*2200;
q=(a/t)+(b/L);
f = ( b - (Q/(T-Tmi)) ) * (b/(L*L*q*q)) - exp(-1/q);
end
Changing the value of the parameter 'X' each time, I can use "fsolve(#crd,10)" from the Command Window multiple times. But I want to do this using a loop.
I want to get solution for X=0.1,0.2,...,0.9,1.0
One possible way to do this is to change your function to accept two parameters: m and X:
function f = crd(m,X)
....
end
Then, when you want to call fsolve, you can create a temporary function that accepts a single parameter m, and pass an actual value for X to it. That is:
for X = [0.1, 0.2, 0.3, 0.4]
f = #(m) crd(m,X); % a function that accepts m as input
sol = fsolve(f, 10);
...
end
I have a use case as follows:
Inside F.m I have a function F that takes as its argument a 2 x 1 matrix x. F needs to matrix multiply the matrix kmat by x. kmat is a variable that is generated by a script.
So, what I did was set kmat to be global in the script:
global kmat;
kmat = rand(2);
In F.m:
function result = F(x)
global kmat;
result = kmat*x;
end
Then finally, in the script I have (x_0 has already been defined as an appropriate 2 x 1 matrix, and tstart and tend are positive integers):
xs = ode45(F, [tstart, tend], x_0);
However, this is causing the error:
Error using F (line 3)
Not enough input arguments.
Error in script (line 12)
xs = ode45(F, [tstart, tend], x_0);
What is going on here, and what can I do to fix it? Alternatively, what is the right way to pass kmat to F?
Firstly, the proper way to handle kmat is to make it an input argument to F.m
function result = F(x,kmat)
result = kmat*x;
end
Secondly, the input function to ode45 must be a function with inputs t and x (possibly vectors, t is the dependent variable and x is the dependent). Since your F function doesn't have t as an input argument, and you have an extra parameter kmat, you have to make a small anonymous function when you call ode45
ode45(#(t,x) F(x,kmat),[tstart tend],x_0)
If your derivative function was function result=derivative(t,x), then you simply do ode45(#derivative,[tstart tend],x_0) as Erik said.
I believe F in ode45(F,...) should be a function handle, i.e. #F. Also, you can have a look at this page of the MATLAB documentation for different methods to pass extra parameters to functions.
If I have a symbolic function p(r,s) = r^3 in MATLAB, I obtain the derivatives dp/dr = 3r^2 and dp/ds = 0, but my goal is to use matlabFunction to convert these expressions to function handles, with vector inputs (r,s). I want something similar to zeros(size(s)), for the derivative dp/ds so I don't obtain a scalar output if my input (r,s) is a vector.
This code I tried:
syms r s
p = r^3
dpds = diff(p,s)
gives a scalar zero not variable size zero, i.e scalar output if we have vector input.
This is the nature of how matlabFunction works. If you provide an equation that has no independent variables as part of the equation, it will default to giving you an anonymous function with no inputs and give you a scalar result.
For example:
>> syms r s;
>> p = r^3;
>> dpds = diff(p,s);
>> dpdsFunc = matlabFunction(dpds)
dpdsFunc =
#()0.0
This will only give you a single scalar value each time. This also applies to any scalar function that gives a non-zero output. If you'd like to override this behaviour and give a variable length of this scalar that is dependent on the length of the input, you can first detect if there are any input variables in the function by checking how many variables there are. You can use symvar for that. You would check if this array has a length of 0, and if it does, you override the function.
Something like this comes to mind:
syms r s;
p = r^3;
dpds = diff(p,s);
if numel(symvar(dpds)) == 0
dpdsFunc = #(s) ones(size(s))*double(dpds); %// Thanks Daniel!
else
dpdsFunc = matlabFunction(dpds);
end
This should achieve what you want.
Minor Note
I actually think this variable length of zeroes business is something that should be put into MATLAB by default, rather than defaulting to a single value. It makes vectorizing code a lot easier. I'm tempted to submit a feature request to MathWorks in the future.
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}