Question

I'm trying to use the MATLAB function fzero properly but my program keeps returning an error message. This is my code (made up of two m-files):

friction_zero.m

function fric_zero = friction_zero(reynolds)
    fric_zero = 0.25*power(log10(5.74/(power(reynolds,0.9))),-2);

flow.m

function f = flow(fric)
    f = 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
    f_initial = friction_zero(power(10,4));
    z = fzero(@flow,f_initial)

The goal is to return z as the root for the equation specified by f when flow.m is run.

I believe I have the correct syntax as I have spent a couple of hours online looking at examples. What happens is that it returns the following error message:

"Undefined function or variable 'fric'."

(Of course it's undefined, it's the variable I'm trying to solve!)

Can someone point out to me what I've done wrong? Thanks

EDIT

Thanks to all who helped! You have assisted me to eventually figure out my problem. I had to add another file. Here is a full summary of the completed code with output.

friction_zero.m

function fric_zero = friction_zero(re)

fric_zero = 0.25*power(log10(5.74/(power(re,0.9))),-2); %starting value for fric

flow.m

function z = flow(fric)

re = power(10,4);

z = 1/(sqrt(fric))-1.873*log10(re*sqrt(fric))-233/((re*sqrt(fric))^0.9)-0.2361;

flow2.m

f_initial = friction_zero(re); %arbitrary starting value (Reynolds)

x = @flow;

fric_root = fzero(x,f_initial)

This returns an output of:

fric_root = 0.0235

Which seems to be the correct answer (phew!)

I realised that (1) I didn't define reynolds (which is now just re) in the right place, and (2) I was trying to do too much and thus skipped out on the line x = @flow;, for some reason when I added the extra line in, MATLAB stopped complaining. Not sure why it wouldn't have just taken @flow straight into fzero().

Once again, thanks :)

Was it helpful?

Solution

You need to make sure that f is a function in your code. This is simply an expression with reynolds being a constant when it isn't defined. As such, wrap this as an anonymous function with fric as the input variable. Also, you need to make sure the output variable from your function is z, not f. Since you're solving for fric, you don't need to specify this as the input variable into flow. Also, you need to specify f as the input into fzero, not flow. flow is the name of your main function. In addition, reynolds in flow is not defined, so I'm going to assume that it's the same as what you specified to friction_zero. With these edits, try doing this:

function z = flow()
    reynolds = power(10,4);
    f = @(fric) 1/(sqrt(fric))-1.873*log10(reynolds*sqrt(fric))-233/((reynolds*sqrt(fric))^0.9)-0.2361;
    f_initial = friction_zero(reynolds);
    z = fzero(@f, f_initial); %// You're solving for `f`, not flow.  flow is your function name

OTHER TIPS

The reason that you have a problem is because flow is called without argument I think. You should read a little more about matlab functions. By the way, reynolds is not defined either.

I am afraid I cannot help you completely since I have not been doing fluid mechanics. However, I can tell you about functions.

A matlab function definition looks something like this:

function x0 = f(xGuess)
    a = 2;
    fcn =@(t) a*t.^3+t; % t must not be an input to f.
    disp(fcn);
    a = 3;
    disp(fcn);
    x0 = fsolve(fcn1,xGuess); % x0 is calculated here

The function can then ne called as myX0 = f(myGuess). When you define a matlab function with arguments and return values, you must tell matlab what to do with them. Matlab cannot guess that. In this function you tell matlab to use xGuess as an initial guess to fsolve, when solving the anonymous function fcn. Notice also that matlab does not assume that an undefined variable is an independent variable. You need to tell matlab that now I want to create an anonymous function fcn which have an independent variable t.

Observation 1: I use .^. This is since the function will take an argument an evaluate it and this argument can also be a vector. In this particulat case I want pointwise evaluation. This is not really necessary when using fsolve but it is good practice if f is not a matrix equation, since "vectorization" is often used in matlab.

Observation 2: notice that even if a changes its value the function does not change. This is since matlab passes the value of a variable when defining a function and not the variable itself. A c programmer would say that a variable is passed by its value and not by a pointer. This means that fcn is really defined as fcn = @(x) 2*t.^3+t;. Using the variable a is just a conveniance (constants can may also be complicated to find, but when found they are just a value).

Armed with this knowledge, you should be able to tackle the problem in front of you. Also, the recursive call to flow in your function will eventuallt cause a crash. When you write a function that calls itself like this you must have a stopping criterium, something to tell the program when to stop. As it is now, flow will call ifself in the last row, like z = fzero(@flow,f_initial) for 500 times and then crash. Alos it is possible as well to define functions with zero inputs:

function plancksConstant = h()
    plancksConstant  = 6.62606957e−34;

Where the call h or h() will return Plancks constant.

Good luck!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top