Run a script 5 times whilst changing the value of one parameter each time.
1 次查看(过去 30 天)
显示 更早的评论
Hi everyone
I would like to run the attached script 5 times whilst changing the value of kga from 4e-1 to 4e-2, then 4e-3, then 4e-4, then 4e-5. I would also like to plot the respective results of the repeats on the same set of axis for each respective figure. I would like to ask for help on how to do it.
Regards
Dursman
23 个评论
Walter Roberson
2018-12-17
Your code assigns a value to kga each time . You cannot run that script with different values of kga. You would have to modify the script .
You should consider making the script into aa function that accepts kga as a parameter .
Stephen23
2018-12-17
Easy way: convert the script to a function and supply kga as an input argument.
I would also recommend that you get rid of those thousand global variables and use nested functions or one structure to parametrize your function:
Jan
2018-12-17
A bunch of global variables is a really bad design. As in all languages using globals is prone to errors and hard to debug. The invisible dependencies increase the complexity of the code massively, therefore experienced programmers avoid them. This has been discussed very frequently and if you are interested in clean and stable programming techniques you can search in this forum.
Using functions with inputs and outputs instead of of a script with global variables will solve your question implicitly and directly.
Dursman Mchabe
2018-12-17
Thanks a lot for the comments and suggestions. It seems the best option is to convert the script into a function. I will quickly learn how to do that as well as to avoid the excessive use of globals.
Dursman Mchabe
2018-12-18
Hello everyone, I have worked on suggestions given above. I have modified the script into a function, and passed kga and other constant values as Parameter(1) ... Parameter(32). When I run the code I get the error message:
Error using fzero (line 139)
Argument 3 must be an options structure.
Error in Repeat1 (line 82)
pH = fzero (@HionpH,pH1,Parameter);
From which I understand that I must pass Parameter as an option structure, when I do, following
I get the following error message:
Error using optimset (line 249)
Unrecognized parameter name 'Parameter(1)'. Please see the options table in the documentation for a list of acceptable option parameters. Note
that some parameters are only supported by OPTIMOPTIONS. Link to options table
Error in Repeat1 (line 59)
options = optimset('Parameter(1)',8.314,'Parameter(2)',149,'Parameter(3)',5.15e+3,'Parameter(4)',1.39e-9,'Parameter(5)',2.89e-9, ...
When I check the table from
I do not see any alternative way.
I have attached the updated m-file.
What can I try?
Walter Roberson
2018-12-18
Dursman Mchabe
2018-12-18
Thanks a lot for such a quick response Walter. Are you suggesting that I should try nested functions? Because, I thought it is parameterized in the state it is right now.
Stephen23
2018-12-18
编辑:Stephen23
2018-12-18
"Because, I thought it is parameterized in the state it is right now."
Nope. The link that Walter Roberson and I both gave you explains two ways to parameterize functions: either nested functions or an anonymous function. You have not used either of those.
The third argument of fzero allows you to specify options for fzero, but this has nothing to do with the parameterizing the function. You will need to do something like this:
S.R = 8.314;
S.HS02 = 149;
...
val = fzero(@(x)yourfun(x,S),x0)
Note that using a scalar structure is probably clearer and less liable to bugs.
Dursman Mchabe
2018-12-18
Thanks a lot Stephen. I think I now understand how to apply parameterization to fzero, but how should I apply it to the function itself?
Stephen23
2018-12-18
编辑:Stephen23
2018-12-18
"I think I now understand how to apply parameterization to fzero, but how should I apply it to the function itself?"
I have no idea what you mean by "apply parameterization to fzero".
My previous comment shows how to parameterize the function yourFun (which is used as the first input to fzero). Perhaps this parameterization might be clearer if the anonymous function is defined on its own line:
S.R = 8.314;
S.HS02 = 149;
...
fun = @(x)yourfun(x,S);
val = fzero(fun,x0)
Note that it is yourFun that has been parameterized, not fzero.
Dursman Mchabe
2018-12-18
编辑:Dursman Mchabe
2018-12-18
The original problem have 2 algebraic equations that are being solved using fzero, and 7 ODEs that are being solved using euler method. For every iteration, the output of algebraic equations is used as initial conditions for ODEs. Likewise, the output of ODEs is used as the initial condition for algebraic equations.
What I meant by applying 'parameterization to fzero' is parameterization of algebraic equations being solved by fzero.
I have converted the script of calling these functions into a function. So what I am not clear about is whether/how to apply parameterization to these functions (i.e functions solving the ODEs and the calling function).
Dursman Mchabe
2018-12-19
Thankyou so so somuch for the suggestion of:
S.R = 8.314;
S.HS02 = 149;
...
val = fzero(@(x)yourfun(x,S),x0)
I have implemented it successfully. It worked. Now, I would like to modify the code such that it runs times whilst changing the value of S.kga from 4e-1 to 4e-2, then 4e-3, then 4e-4, then 4e-5. I would also like to plot the respective results of the repeats on the same set of axis for each respective figure. I will do the same for all other parameters. How can I do it?
madhan ravi
2018-12-19
编辑:madhan ravi
2018-12-19
you can run a loop with S.kga as input (parameterize your function) like
for kga=[4e-1, 4e-2, 4e-3 , 4e-4] %change S.kga to kga
repeat(...,kga)
end
Dursman Mchabe
2018-12-19
Thanks a lot for the comment Madhan. I appreciate. I am not clear about two things:
(1) I am not sure where to put:
for kga =[4e-1, 4e-2, 4e-3 , 4e-4, 4e-5]
repeat(Repeat1(y,S,kga))
end
(2) I am also not sure where to and not to pass kga as an input.
After implenting the suggestion (to the best of my limited understanding), I get the following error:
Unable to perform assignment because the left and right sides have a different number of elements.
Error in Repeat1>NSub (line 331)
discrep(2) = Rate_gas - Rate_liq ;
Error in Repeat1>@(Tr)NSub(Tr,S,kga) (line 264)
Tnew = fsolve (@(Tr)NSub(Tr,S,kga),Trial);
Error in fsolve (line 242)
fuser = feval(funfcn{3},x,varargin{:});
Error in Repeat1>odes (line 264)
Tnew = fsolve (@(Tr)NSub(Tr,S,kga),Trial);
Error in Repeat1>SO2_OdeDriver (line 215)
dydt = odes (t, y0,S,kga);
Error in Repeat1 (line 108)
y = SO2_OdeDriver(y0,S);
Caused by:
Failure in initial objective function evaluation. FSOLVE cannot continue.
I have attached a script to my current code.
Jan
2018-12-19
It is hard to help you to solve the problem, because the internal communication between the different parts of your code is implemented by global variables. This make the code very unclear and hard to maintain. Please blame the one who has given you this code.
A proper indentation would improve the readability at least: Open the file in the editor and press Ctrl-A Ctrl-I.
Stephen23
2018-12-19
编辑:Stephen23
2018-12-19
@Dursman Mchabe: your approach to programming is known as the "shotgun" method: you defined kga as an input and also redefined it within every local function (except one), e.g.:
function discrep = NSub (Tr,S,kga)
...
kga = [4e-1, 4e-2, 4e-3 , 4e-4, 4e-5] ;
What use is that input argument when you just throw it away when you redefine kga a few lines later? In every local function excep that last one. It is not clear how that would work.
In any case, try something like this:
kga = [4e-1, 4e-2, 4e-3, 4e-4, 4e-5];
num = numel(kga);
out = cell(1,num);
for k = 1:num
out{k} = Repeat1(kga(k));
end
And within Repeat1 just do this assignment once so that its value will be available in the structure S, so you just need to pass S (which is the whole point of having S):
function Result = Repeat1(kga)
...
S.kga = kga;
...
end
And then get rid of all of the those other kga definitions that you liberally spread around throughout your code.
Get rid of the global variables and pass all parameters by parameterizing the functions:
Dursman Mchabe
2018-12-19
编辑:Dursman Mchabe
2018-12-19
Thanks a lot for the comment @Jan. I am affraid, if I blame the person who gave me the code, he might not help me in future. He was just helping a strugling student.
Dursman Mchabe
2018-12-19
Thanks a lot once again @Stephen for the suggestion. It looks very promising, I am still busy implimenting it. I trust that it will work.
I was too affraid to get rid of global variables, I will try it as well.
Dursman Mchabe
2018-12-19
@Stephen, I am being pushed towards using the 'shortgun method' , because using:
kga = [4e-1, 4e-2, 4e-3, 4e-4, 4e-5];
num = numel(kga);
out = cell(1,num);
for j = 1:num
out{j} = Repeat1(kga(j));
end
inside Repeat1 function leads to a recursion error:
Out of memory. The likely cause is an infinite recursion within the program.
Error in Repeat1 (line 44)
out{j} = Repeat1(kga(j));
The automatic response in my mind is to put
kga = [4e-1, 4e-2, 4e-3, 4e-4, 4e-5];
num = numel(kga);
out = cell(1,num);
for j = 1:num
out{j} = Repeat1(kga(j));
end
in every local function, except, Repeat1. Is there any other approach?
Stephen23
2018-12-19
编辑:Stephen23
2018-12-19
"The automatic response in my mind is to put ... in every local function, except, Repeat1."
And what would that do? Don't just guess or wait for some random stranger to explain what it would do: experiment! Write a few simple local functions in an Mfile, that call each other. Add the same loop to each function. What happens? Does it really do what you want?
Write down the sequence of operations on a piece of paper, or use the debugging tools to track how your code executes: which lines, which functions, etc. Do not just guess and use the shotgun approach.
Tip1: learn another automatic response: less is more.
"Is there any other approach?"
Of course: do not write a recursive function, by NOT calling Repeat1 on line 44 of Repeat1. In your original code (the script attached to your question) the script did not call itself. So why are you doing that now?
Your original question asked "I would like to run the attached script 5 times whilst changing the value of kga ..." and you have been advised by two people to do use a loop, essentially something like this:
for kga = [...]
... all of your script (converted to a function) here.
end
And that would indeed resolve your question.
No one advised you to hide loop/s inside your code and then call the function itself on line 44 (and from other locations). For some reason you decided to add loops somewhere inside your code.... of course experimentation is a good thing: thus you have learned that when you call a function from inside itself it leads to recursion. However recursion is not what you want to do to solve this problem.
The loop we showed you should NOT be written anywhere inside Repeat1. That probably means that it should be in its own script (simpler). Or, if you really want all of your code to be in the same file, then create a new main function so that Repeat1 is now just a local function, e.g.:
function out = mymainfun(vec)
num = numel(vec);
out = cell(1,num);
for k = 1:num
out{k} = Repeat1(vec(k));
end
end
function results = Repeat1(kga)
... all of your code here. No kga loops!
end
Tip2: Start small. Forget about your code. Take this small example and grow it: first just display kga inside Repeat1, then add the other parameter definitions, then add the other local functions, one at a time, passing the parameters properly. Test, Check, Progress.
Dursman Mchabe
2018-12-19
Thanks a lot for your comment and a very clear explaination. I appreciate that you are providing your expertize. I learn a lot everyday.
I like the idea of using:
function out = mymainfun(vec)
num = numel(vec);
out = cell(1,num);
for k = 1:num
out{k} = Repeat1(vec(k));
end
function results = Repeat1(kga)
... all of your code here. No kga loops!
end
I have implemented it, however, there seems to be an outstanding input. Because I get the error message:
>> mymainfun
Not enough input arguments.
Error in mymainfun (line 2)
num = numel(vec);
>>
I am trying different inputs.
Stephen23
2018-12-19
编辑:Stephen23
2018-12-19
I wrote mymainfun so that you could input any vector of kga values without hardcoding them, which means that you will need to call the function with those values, e.g.:
tmp = [4e-1, 4e-2, 4e-3, 4e-4, 4e-5];
out = mymainfun(tmp);
If you prefer to have have hardcoded values then just get rid of the input argument and write that vector inside the function:
function out = mymainfun()
vec = [4e-1, 4e-2, 4e-3, 4e-4, 4e-5];
num = numel(vec);
out = cell(1,num);
for k = 1:num
out{k} = Repeat1(vec(k));
end
end
... etc
You are the code's designer, so these things are entirely up to you.
Dursman Mchabe
2018-12-19
Thank you so so somuch. The code works 100%. I still have a veery long way to go in learning matlab. But I believe that one day I will be good. I will keep on reading, asking and trying. I thank you so so somuch for everythink that I have learnt yesterday and today.
回答(0 个)
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Logical 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!发生错误
由于页面发生更改,无法完成操作。请重新加载页面以查看其更新后的状态。
您也可以从以下列表中选择网站:
如何获得最佳网站性能
选择中国网站(中文或英文)以获得最佳网站性能。其他 MathWorks 国家/地区网站并未针对您所在位置的访问进行优化。
美洲
- América Latina (Español)
- Canada (English)
- United States (English)
欧洲
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
亚太
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)