Scilab - define a function inside another one - function

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.

Related

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:

Differential equation; function in Octave

I try to solve a differential equation in Octave. In a first attempt, all my independent variables are set constant (n,y,w). This is my code:
function xdot= f(x,t);
% xdot=zeros(1,1);
X=1.44221E+12;
IO=5.318E+11;
GO=6.81E+11;
beta=0;
gamma=0;
y=58.5021088;
w= 31.29;
n=1363.5;
tw=0.4;
tp=0.3;
sw=0.07;
sp=0.25;
mw=0.593941689;
mp=0.593941689;
% aw=(1-tw)(sw+mw)
% ap=(1-tp)(sp+mp)
xdot=-(X+IO*(1+gamma*(diff(n)/n+diff(y)/y))+GO*beta(tw(diff(n)/n+diff(w)/w)+tp(diff(y)/y-diff(w)/w)-(x*n)/((y-w)((1-tp)(sp+mp)+tp)+((1-tw)(sw+mw)+tw)*w))*x)/(IO*gamma+GO*beta*tw);
endfunction
When I add
t = [0:(1/360):10]
x = lsode ("f", 39290000, t);
to solve the equation in the command line, I get this error:
error: index (0.843942): subscripts must be either integers 1 to (2^31)-1 or logicals
error: lsode: evaluation of user-supplied function failed
error: called from
f at line 23 column 7
It seems to me, in some way I misunderstood how to make the function.
Any help?
EDIT:
This is my new code:
function xdot= f(x,t);
X=1.44221E+12;
IO=5.318E+11;
GO=6.81E+11;
beta=0;
gamma=0;
y=58.5021088;
w= 31.29;
n=1363.5;
tw=0.4;
tp=0.3;
sw=0.07;
sp=0.25;
mw=0.593941689;
mp=0.593941689;
xdot=-X+IO-(x*n)/((y-w)*((1-tp)*(sp+mp)+tp)+w*(tw+(1-tp)*(sp+mp)))
endfunction
It does work if I copy it into the command line but if I start it as programm (f.m) and solve it then I get this error:
error: 'x' undefined near line 25 column 15
error: called from
f at line 25 column 7
From the documentation of lsode:
Syntax: [x, istate, msg] = lsode (fcn, x_0, t)
...
The first argument, fcn, is a string, inline, or function handle that names the function f to call to compute the vector of right hand sides for the set of equations. The function must have the form
xdot = f (x, t)
in which xdot and x are vectors and t is a scalar.
So firstly, your f function is of the wrong form to the one expected by lsode, since it takes 5 arguments as opposed to 2.
Secondly, inside your f function, the variables y, w, and n are overwritten, regardless of whether they were supplied, whereas t and x need to be supplied by the user.
When lsode calls the handle f, it calls it with two arguments as per its specification, which means it instantiates t and y, and calls the function with the remaining input arguments undefined. Of the remaining arguments, w and n are given values inside the function, as we pointed out above, but x remains undefined. So when you run the final calculation which relies on x, you get an error saying it has not yet been defined during the call to this function.
So, to fix this issue, rewrite your function such that its signature is f(x, t), which you can do so easily since y, w, and n are defined inside your function anyway, so they don't really need to be given as inputs.

Scilab not returning variables in variable window

I have created a function that returns the magnitude of a vector.the output is 360x3 dimension matrix. the input is 360x2.
Everything works fine outside the function. how do i get it to work ?
clc
P_dot_ij_om_13= rand(360,2); // 360x2 values of omega in vectors i and j
//P_dot_ij_om_13(:,3)=0;
function [A]=mag_x(A)
//b="P_dot_ijOmag_"+ string(k);
//execstr(b+'=[]'); // declare indexed matrix P_dot_ijOmag_k
//disp(b)
for i=1:1:360
//funcprot(0);
A(i,3)=(A(i,2)^2+A(i,1)^2)^0.5; //calculates magnitude of i and j and adds 3rd column
disp(A(i,3),"vector magnitude")
end
funcprot(1);
return [A] // should return P_dot_ijOmag_k in the variable browser [360x3 dim]
endfunction
mag_x(P_dot_ij_om_13);
//i=1;
//P_dot_ij_om_13(i,3)= (P_dot_ij_om_13(i,2)^2+P_dot_ij_om_13(i,1)^2)^0.5;// example
You never assigned mag_x(P_dot_ij_om_13) to any variable, so the output of this function disappears into nowhere. The variable A is local to this function, it does not exist outside of it.
To have the result of calculation available, assign it to some variable:
res = mag_x(P_dot_ij_om_13)
or A = mag_x(P_dot_ij_om_13) if you want to use the same name outside of the function as was used inside of it.
By the way, the Scilab documentation discourages the use of return, as it leads to confusion. The Scilab / Matlab function syntax is different from the languages in which return specifies the output of a function:
function y = sq(x)
y = x^2
endfunction
disp(sq(3)) // displays 9
No need for return here.

Writing a function m-file in MATLAB

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