Writing a function m-file in MATLAB - function

I am a beginner to coding and I need to write a function.m file for use with Newton's Method. I am having trouble defining the function, where r is radius and p is density:
f(theta) = ((r^2)/2)*((2*pi*p)-(theta - sin(theta)*p))
where radius r = 30cm and density p = 0.82 grams per cm^3
So far, I have written:
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
Things I am having trouble with:
Problem defining r and p. Getting an error:
Undefined function or variable 'r'
Having trouble plotting the function.
Things I want to do:
Plot the function to see where the roots are.
Be able to evaluate the function for a given theta.
All help is appreciated. Thank you!

i tried your code without changing. i named the M-file as f1 and executed the function in command line it is working.
function y = f1(theta)
r = 0.3;
p = 0.82;
y = (r^2)/2*(2*pi*p - (theta - sin(theta)*p));
i am getting the output as below
f=f1(45)
f =
-1.7618
this tells that there is no problem in your function. see for some other reason. if you could give your whole code it would be better to diagnose.

This could be done using an anonymous function
r=0.3;
p=0.82;
f=#(theta) (r^2)/2*(2*pi*p-theta+p*sin(theta));
then to evaluate the function just use eg: f(1), and to plot it, for example:
angles=0:.01:pi;
plot(angles,f(angles))
If you don't want to use an anonymous function, then use
function funcVal=func(angles)
r=0.3;
p=0.82;
funcVal=(r^2)/2*(2*pi*p-angles+p*sin(angles));
end
and call it by
angles=0:.01:pi;
plot(angles,func(angles))

Related

Scilab - define a function inside another one

I want to define a function that takes an input n and gives back the function f defined by f(x) = x^n.
So I wrote the following piece of code on Scilab:
function [f]=monomial(n)
function [z] = g(x)
z = x^n
endfunction
f = g
endfunction
Unfortunately when I evaluate monomial(3)(2) I get 32. whereas it should be 8.
I hope someone could point out where I have gone wrong when writing this function.
Could somebody help me please?
I cleared all variables and reran the code and it told me that n is not defined within g, therefore is there a way to overcome this problem?
the more secure way to do this is by using deff :
function [f]=monomial(n)
f = deff('z=g(x)','z=x^'+string(n));
endfunction
otherwise n could be polluted by current scope
--> monomial(2)(8)
ans =
64.

How to define a function with a parameter in it in Octave?

I am trying to define a function with a predefined variable, and Octave says that the variable was not defined. I am trying to run the following code in Octave,
q = 5;
function w = tointegrate(x)
w = 2 * q * sin(x);
endfunction
[ans, ier, nfun, err] = quad("tointegrate", -10*q, 10*q);
ans
Octave gives the error
error: 'q' undefined near line 3 column 10
error: quad: evaluation of user-supplied function failed
How to fix this error?
You are expecting 'commandline functions' in octave to have lexical scope, but this is simply not the case.
If all of this was inside a function, and you defined a nested function, it would work as you expect. But 'commandline functions' like this are treated as if they are in their own file, and have no knowledge of the workspace in which they've been defined.
In this particular case, since your function is effectively a one-liner, you can get the effect you want by making it a function handle instead, which 'does' capture the local workspace. I.e. this will work
q = 5;
tointegrate = #(x) 2 * q * sin(x);
[ans, ier, nfun, err] = quad("tointegrate",-10 *q ,10*q);
Note, however, that 'q' will have the value it had at the time it was captured. I.e. if you update q dynamically, its value will not be updated in the function handle.
Otherwise, for more complex functions, the solution is really to pass it as a parameter (or to access it as a global etc).
You can solve this by having q be a parameter to the function, then creating an anonymous function to call quad, like so:
function w = tointegrate(x, q)
w = 2 * q * sin(x);
endfunction
q = 5;
[ans, ier, nfun, err] = quad(#(x)tointegrate(x,q), -10*q, 10*q);
ans

How to solve a second order differential equation on Scilab?

I need to solve this differential equation using Runge-Kytta 4(5) on Scilab:
The initial conditions are above. The interval and the h-step are:
I don't need to implement Runge-Kutta. I just need to solve this and plot the result on the plane:
I tried to follow these instructions on the official "Scilab Help":
https://x-engineer.org/graduate-engineering/programming-languages/scilab/solve-second-order-ordinary-differential-equation-ode-scilab/
The suggested code is:
// Import the diagram and set the ending time
loadScicos();
loadXcosLibs();
importXcosDiagram("SCI/modules/xcos/examples/solvers/ODE_Example.zcos");
scs_m.props.tf = 5000;
// Select the solver Runge-Kutta and set the precision
scs_m.props.tol(6) = 6;
scs_m.props.tol(7) = 10^-2;
// Start the timer, launch the simulation and display time
tic();
try xcos_simulate(scs_m, 4); catch disp(lasterror()); end
t = toc();
disp(t, "Time for Runge-Kutta:");
However, it is not clear for me how I can change this for the specific differential equation that I showed above. I have a very basic knowledge of Scilab.
The final plot should be something like the picture bellow, an ellipse:
Just to provide some mathematical context, this is the differential equation that describes the pendulum problem.
Could someone help me, please?
=========
UPDATE
Based on #luizpauloml comments, I am updating this post.
I need to convert the second-order ODE into a system of first-order ODEs and then I need to write a function to represent such system.
So, I know how to do this on pen and paper. Hence, using z as a variable:
OK, but how do I write a normal script?
The Xcos is quite disposable. I only kept it because I was trying to mimic the example on the official Scilab page.
To solve this, you need to use ode(), which can employ many methods, Runge-Kutta included. First, you need to define a function to represent the system of ODEs, and Step 1 in the link you provided shows you what to do:
function z = f(t,y)
//f(t,z) represents the sysmte of ODEs:
// -the first argument should always be the independe variable
// -the second argument should always be the dependent variables
// -it may have more than two arguments
// -y is a vector 2x1: y(1) = theta, y(2) = theta'
// -z is a vector 2x1: z(1) = z , z(2) = z'
z(1) = y(2) //first equation: z = theta'
z(2) = 10*sin(y(1)) //second equation: z' = 10*sin(theta)
endfunction
Notice that even if t (the independent variable) does not explicitly appear in your system of ODEs, it still needs to be an argument of f(). Now you just use ode(), setting the flag 'rk' or 'rkf' to use either one of the available Runge-Kutta methods:
ts = linspace(0,3,200);
theta0 = %pi/4;
dtheta0 = 0;
y0 = [theta0; dtheta0];
t0 = 0;
thetas = ode('rk',y0, t0, ts, f); //the output have the same order
//as the argument `y` of f()
scf(1); clf();
plot2d(thetas(2,:),thetas(1,:),-5);
xtitle('Phase portrait', 'theta''(t)','theta(t)');
xgrid();
The output:

MATLAB str2func to send function

I want to pass function(string) from uicontrol via my GUI, and how properly use str2func to send function into my m file.
Piece of my GUI.m file
function functionbox_Callback(hObject, eventdata, handles)
fun= str2func(get(handles.functionbox, 'String'));
[x, y] = hessian(fun);
Piece of my hessian.m file where i want to pass function from GUI:
function [x, y] = hessian(fun)
f = #(x,y) fun;
blablabla
hold off
How I can do this kind of method.
If I understood correctly your question you have pretty much figured it out. What is missing from your code would be to call f with appropriate input arguments to obtain the outputs x and y.
Consider this code which is based on yours. The use enters a function in the lefthand box and the output (actually x+y...just for the demo) is displayed in the righthand box. Play around with it too see how the functions work together. Please ask if something is unclear.
Code:
function LoadFun
clear
clc
hfigure = figure('Position',[200 200 300 300]);
handles.TextFunction = uicontrol('Style','Text','Position',[20 220 100 20],'String','Enter function');
handles.functionbox = uicontrol('Style','edit','Position',[20 200 100 20],'String','');
handles.TextResult = uicontrol('Style','Text','Position',[140 220 100 20],'String','Output');
handles.resultbox = uicontrol('Style','edit','Position',[140 200 100 20],'String','');
handles.Button = uicontrol('Style','push','Position',[20 160 100 20],'String','Call function','Callback',#(s,e) ButtonCallback);
%// Call the function
function ButtonCallback
fun= str2func(get(handles.functionbox, 'String'));
[x,y] = hessian(fun);
%// Make other calculation and display output;
z = x+y;
set(handles.resultbox ,'String',num2str(z));
end
%// Your function
function [x,y] = hessian(fun)
%// Define handles. Inputs do not have to be x and y here.
f = #(a,b) fun(a) + fun(b);
%// Perform operations
x = f(pi,pi/2);
y = f(0,2*pi);
end
end
Screenshot:
Hope that is what you were after!
str2func works a lot like the function-handle #.
So if your input looks something like this:
'#(x,y) x+y'
or
'functionname'
it should work just fine.
To pass the, now, function handle to your GUI, you do not need to define it again:
function [x, y] = hessian(fun)
result=fun(data);
blablabla hold off
As for multiple Outputs of anonymous-functions:
it is possible, but, as far as I know, not inline.
Source:http://ch.mathworks.com/help/matlab/matlab_prog/anonymous-functions.html#f4-70159
But this is easily solved with arrays.

MATLAB function syntax within script?

Having some trouble declaring functions within my script:
%Read the raw audio data
refData = wavread('file1.wav');
userData = wavread('file2.wav');
% I want to continue writing my "main" function here, and call the below functions
%%%%%%%%%%%%%
% Functions %
%%%%%%%%%%%%%
%Vector x
function preEmphasis(x)
alpha = 0.95;
len = length(x);
for i=1:len
x_i = x(i);
x_iMinus1 = x(i-1);
x(i) = x_i - alpha*x_iMinus1;
end
end
%Vector x
function normalization(x)
maxVal = max(abs(x));
x = x / maxVal;
end
%Vector x; numFrames, frameSize: integers; stepSize: percentage (float, 0.2 -> 0.5 for example)
function Ymatrix = createYmatrix(x, numFrames, frameSize, stepSize)
Ymatrix = zeros(numFrames, frameSize);
for i=1:numFrames
for j=1:frameSize
Ymatrix(i,j) = x(stepSize*i + j);
end
end
end
The words "function" and "end" are highlighted in red as "parse errors". How can I fix this? Thanks.
You can't declare functions within your main script. You have to create an external m-file and implement your function inside it, like it says in the official documentation:
Any function that is not anonymous must be defined within a file.
(just to be clear, a script does not accept input arguments or return output arguments).
However, you can have local functions declared inside a function m-file.
Read more about function declarations in the official documentation.
EDIT: You can Refer to #natan's answer if you're looking for a way to avoid function m-files altogether. He implemented your functions as anonymous functions, which can be declared inside the script file. Good luck!
In Addition to what Eitan mentioned, here is how to implement an anonymous functions in your case, note that code vectorization is a must. For example, in your case instead of normalization you can write:
normalization = #(x) x./max(abs(x));
and then use it as if it was a function, y=normalization(x)
For preEmphasis:
preEmphasis= #(x) [x(1) x(2:end)-0.95*x(1:end-1)];
Your current code has a bug for the case i=1 so I interpret that as for=2:len instead;
The solution for Ymatrix is a bit ugly (haven't invested to much time vectorizing it nicely), but it should work:
Ymatrix = #(x, numFrames, frameSize, stepSize) ...
ones(1,numFrames)'*x(1+stepSize:stepSize+frameSize)+...
meshgrid(0:stepSize:stepSize*numFrames-1,ones(1,frameSize))';
Just turn your script into a function; then you can use local and nested functions. Use return values or assignin if you need to get values back in to the base or caller's workspace.