Not able to solve fzero with array by for-loop

3 views (last 30 days)
Hello everybody,
I'm working on my thesis and I got stuck for few hours/days on this:
  • Having implicit function with array (15x1) with one vairable (results needed for all array positions)
I've spend few hours running through this forum (attempt on solving my issue by seen examples is the second/lower code) and I am starting to become hopeless. How to properly do it?
Working fzero code with my equation (everything is a scalar besides the lambdaCH_030_4h and Mach030_4h is unknow) I would write it seperatly (write the loop by hand), but I need it for even bigger arrays and multiple other equations.
lambdaCH_030_4h = ones(1,15)' ; %example
c_int = 0.7576
kappa = 1.4
fcn = @(Mach030_4h) ...
((-1)*lambdaCH_030_4h(1,1) + c_int * ...
(( (1 - sqrt(1-(Mach030_4h^2))) / (1 + sqrt(1-(Mach030_4h^2))) ).^(1/2)) * ...
( ((sqrt( (kappa+1) / (kappa-1) )) + sqrt(1-(Mach030_4h^2)) )/ ...
((sqrt( (kappa+1) / (kappa-1) )) - sqrt(1-(Mach030_4h^2)) )) ...
.^((1/2) * ( sqrt( (kappa + 1) / (kappa - 1) ) ))) ;
Mach030_4h = fzero(fcn,0) ;
My try on getting results for all lambdaCH_030_4h, but with no luck.
fcn = @(Mach030_4h) ...
((-1)*lambdaCH_030_4h + c_int * ...
(( (1 - sqrt(1-(Mach030_4h^2))) / (1 + sqrt(1-(Mach030_4h.^2))) ).^(1/2)) * ...
( ((sqrt( (kappa+1) / (kappa-1) )) + sqrt(1-(Mach030_4h.^2)) )/ ...
((sqrt( (kappa+1) / (kappa-1) )) - sqrt(1-(Mach030_4h.^2)) )) ...
.^((1/2) * ( sqrt( (kappa + 1) / (kappa - 1) ) ))) ;
Mach030_4h_V = zeros(1,15)' ;
for i = 1:length(lambdaCH_030_4h)
Mach030_4h_V(i,1) = fzero( @(Mach030_4h) fcn(Mach030_4h,lambdaCH_030_4h(i,1)),0.1) ;
end
This one gets as an error Too many arguments.
Different way I tired to achieve this:
for i = 1:length(lambdaCH_030_4h)
fcn = @(Mach030_4h) ...
((-1)*lambdaCH_030_4h(i,1) + c_int * ...
(( (1 - sqrt(1-(Mach030_4h^2))) / (1 + sqrt(1-(Mach030_4h(i,1).^2))) ).^(1/2)) * ...
( ((sqrt( (kappa+1) / (kappa-1) )) + sqrt(1-(Mach030_4h(i,1).^2)) )/ ...
((sqrt( (kappa+1) / (kappa-1) )) - sqrt(1-(Mach030_4h(i,1).^2)) )) ...
.^((1/2) * ( sqrt( (kappa + 1) / (kappa - 1) ) ))) ;
Mach030_4h_V(i,1) = fzero( fcn,0.1) ;
end
This one gets this error message: Index in position 1 exceeds array bounds. Index must not exceed 1.
Any help would be greatly welcome!
Thanks in advance!!
  4 Comments
dpb
dpb on 30 May 2022
Yes. OK, then just write the function to pass both the existing argument and the particular values fof the other variable in the loop.
Done.
NB: As @Torsten points out, ensure a feasible solution is possible, first, before dispatching fzero on its mission.
dpb
dpb on 30 May 2022
I see that @Torsten actually showed you explicitly how to do what I suggested...
You CAN do what you tried to do with slightly different syntax, but it's MUCH cleaner this way.
To use an array inside the anonymous function would require the second argument anyway to pass the indexing variable that you left out...it doesn't know anything about the for loop; an anonymous function uses static copies of the workspace variables it references AT_THE_TIME_IT_IS_DEFINED and those are unchanged no matter what happens to the same variables afterwards. Only redefiing the function with a different set of variable values will change what happens inside the anonymous function.
Hence, to use it in the loop without passing the second variable, you would define the variable "lambda" as the array value, execute the lines of code that redefine FCN and then sic fzero() on the new result. Much more efficient to pass the constant.
Again, the range of the function as it's written seems very limited to produce real values -- I would also strongly suggest it is too complicated for an anonymous function -- use an m-file and define intermediary values for the various pieces that are used multiple times and then reference those in the long equation.
Then, eliminate about half the superfluous parentheses so the code is legible...

Sign in to comment.

Accepted Answer

Jakub Szekely
Jakub Szekely on 30 May 2022
Edited: Jakub Szekely on 30 May 2022
Thanks anybody for commenting. Dear friend of mine helped me with this and I finally got my much needed values. Solution for this implicit fnc in all possible combinations thru fzero was done with the help of anonymous functions and for-loop (not just for-loop).
For anybody who will found this.
This is what we did:
  1. Created a script with my original implicit function
function y = U5implic(Mach,lambda,kappa,c_int)
y=(-1).*lambda + c_int .* ...
(( (1 - sqrt(1-(Mach.^2))) ./ (1 + sqrt(1-(Mach.^2))) ).^(1/2)) .* ...
( ((sqrt( (kappa+1) ./ (kappa-1) )) + sqrt(1-(Mach.^2)) )./ ...
((sqrt( (kappa+1) ./ (kappa-1) )) - sqrt(1-(Mach.^2)) )) ...
.^((1/2) .* ( sqrt( (kappa + 1) ./ (kappa - 1) ) )) ;
end
2. Create for-loop in your schript
(due to the fncs "geometry" we played a little with the zero/start value (Mach0 =0.2) -> changed it from 0 to 0.1 then to 0.2)
lambdaCH = [lambdaCH_030_4h lambdaCH_042_4h lambdaCH_030_4d...
lambdaCH_042_4d lambdaCH_030_0h lambdaCH_042_0h lambdaCH_030_0d lambdaCH_042_0d] ;
Jan = zeros(15,8) ;
for j= 1:8
lambdaVec=lambdaCH(:,j);
Mach0=0.2;
kappa=1.4;
for i=1:length(lambdaVec)
lambda=lambdaVec(i);
f=@(Mach)U5implic(Mach,lambda,kappa,c_int);
[Jan(i,j),fval]=fzero(f,Mach0);
end
end
Important: the two forloops were used due to the needed of fzero to go through multiple arrays of data (15x1) for this implicit function.
Thank you for your time and strong nerves.
  1 Comment
dpb
dpb on 30 May 2022
That's identically what @Torsten and I told you to do in only a slightly altered incarnation -- his solution deserves being "Accepted" and acknowledged.
You'll note my comment to rewrite the function as an m-file -- I'd certainly have taken it several steps further than that, but ugly is in the eye of the beholder.
If this is, however, thesis or similar project, it desires a far better presenation.

Sign in to comment.

More Answers (1)

Torsten
Torsten on 30 May 2022
Edited: Torsten on 30 May 2022
To see where the problem with fzero is, I suggest you first plot your function for a reasonable value of lambdaCH_030_4h:
c_int = 0.7576;
kappa = 1.4;
lambdaCH_030_4h = 1.0;
fcn = @(Mach030_4h,lambdaCH_030_4h) ...
((-1)*lambdaCH_030_4h + c_int .* ...
(( (1 - sqrt(1-(Mach030_4h.^2)))./ (1 + sqrt(1-(Mach030_4h.^2))) ).^(1/2)).* ...
( ((sqrt( (kappa+1) / (kappa-1) )) + sqrt(1-(Mach030_4h.^2)) )./ ...
((sqrt( (kappa+1) / (kappa-1) )) - sqrt(1-(Mach030_4h.^2)) )) ...
.^((1/2).* ( sqrt( (kappa + 1) / (kappa - 1) ) ))) ;
Mach030_4h = 0.1:0.01:5.0;
plot(Mach030_4h,fcn(Mach030_4h,lambdaCH_030_4h))
Here you see that fzero cannot succeed since your function has no zero (at least in the range I specified).
Once you have found a reasonable range for lambdaCH_030_4h, you can use fsolve:
c_int = 0.7576;
kappa = 1.4;
lambdaCH_030_4h = some array;
fcn = @(Mach030_4h,lambdaCH_030_4h) ...
((-1)*lambdaCH_030_4h + c_int .* ...
(( (1 - sqrt(1-(Mach030_4h.^2)))./ (1 + sqrt(1-(Mach030_4h.^2))) ).^(1/2)).* ...
( ((sqrt( (kappa+1) / (kappa-1) )) + sqrt(1-(Mach030_4h.^2)) )./ ...
((sqrt( (kappa+1) / (kappa-1) )) - sqrt(1-(Mach030_4h.^2)) )) ...
.^((1/2).* ( sqrt( (kappa + 1) / (kappa - 1) ) ))) ;
guess = 1.0;
for i = 1:numel(lambdaCH_030_4h)
fun = @(Mach030_4h) fcn(Mach030_4h,lambdaCH_030_4h(i));
sol(i) = fsolve(fun,guess);
guess = sol(i);
end

Categories

Find more on MATLAB in Help Center and File Exchange

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!