Is there a flag/scripting way of specifying for a simulation :
Store variable at events, same as Simulation Setup\Output\Store variables at events
Equidistant time grid, same as Simulation Setup\Output\Equidistant time grid
I know it can be added as an annotation in model :
annotation experiment(__Dymola_NumberOfIntervals=501), __Dymola_experimentSetupOutput(equdistant=true, events=true));
Regards,
Gilles
I found the answer in from the Dymola support. See the Dymola user manual V1 p 501 on the simulator API :
experimentSetupOutput(...)
input Boolean textual := false "Textual storage";
input Boolean doublePrecision := false "Double precision";
input Boolean states := true "Store state variables";
input Boolean derivatives := true "Store derivative variables";
input Boolean inputs := true "Store input variables";
input Boolean outputs := true "Store outputs variables";
input Boolean auxiliaries := true "Store auxiliary variables";
input Boolean equdistant := true "Store equidistantly";
input Boolean events := true "Store variables at events";
input Boolean debug := false "Write log messages";
output Boolean ok;
Therefore the flags to set before the simulateModel command were :
experimentSetupOutput(events=false,equdistant=true);
Related
The following code
model FunctionCall
Boolean result;
function F
input Real p1;
output Boolean result;
algorithm
result :=p1 < 0.5;
end F;
algorithm
result :=F(time);
end FunctionCall;
(also described in http://www.modelica-forum.com/forums/index.php?showtopic=2) still throws an error in Dymola 2018FD01, while in OpenModelica it is accepted.
Is this wrong Modelica code or a Dymola bug?
Thanks in advance.
The model is incorrect.
3.8 "For an assignment v:=expr or binding equation v=expr, v must be declared to be at least as variable as expr"
Boolean variables are discrete-time expressions according to 3.8.3 "Discrete-time variables, i.e., Integer, Boolean, String variables and enumeration variables, as well as Real variables assigned in when-clauses"
F(time) is not a discrete-time expression, since 3.8.3 only includes "Function calls where all input arguments of the function are discrete-time expressions"
All according to Modelica 3.4.
The reason is that Boolean variables in models should only change at events, and the result of a function such as F(time) can neither guarantee that nor reliably generate events.
Hans answer is the correct one for your question.
Your unasked question may be how one can get the same behavior within the language specifications. Below I have provided one possible solution.
model FunctionCall
Boolean result;
function F
input Real p1;
output Integer result;
algorithm
result := if p1 < 0.5 then 1 else 0;
end F;
algorithm
result := if F(time) < 0.5 then false else true;
end FunctionCall;
I am writing AutoHotkey script, and now confused about how to compare numbers in AutoHotkey. 1>2 is obviously false, but why the MsgBox alerts 1>2 rather than false?
I think this is a boolean comparison, why msgbox don't calculate the result?
This problem is not the same as If Expressions Don't Work .
It's most likely because your code looks like this: MsgBox, (if(1>2))
Which is read by AHK as: Create a message-box, and use the message '(if(1>2))'.
If you want to actually evaluate expressions and use the result as the message, the proper syntax is this: MsgBox, % 1>2
This would print out 0 in the message-box, which is equal to false, since in AHK the words true and false are just built-in variables containing 1 and 0.
I suggest you read this page on Variables and Expressions from the docs. They provide a good insight into how AHK handles variables and expressions, as it can be a bit... special.
msgbox, % check(1 > 2)
return
check(now)
{
if (now)
return "true"
else
return "false"
}
using this function you can check the expression's result and return it to the msgbox!
look at the
%
that makes the msgbox show the RESULT of the expression and not the string its written as (ahk flaw in my opinion)
The exact question would be "is the equation you want to use x=f(Xo)". This is in an if statement already so if true then continue if not then prompt user to enter a different function.
Your bit about its already being inside an if statement isn't very workable because that doesn't allow for an alternative value to be assigned to something in the case that the initial response is negative.
You should be able to work with something like this. Call p(), and assign its result to a ans, say, and then work with that value (and/or test it for some properties).
restart:
p := proc()
local answer, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf("Is the equation you want to use x=f(Xo)? (y/n)\n");
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
answer := x=f(Xo);
elif member(res1,{"n;","n","no;","no"}) then
printf("Enter your equation.\n");
res2 := readline(-1);
answer := parse(res2);
else
printf("Response not recognized\n");
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
if answer='answer' then NULL else answer end if;
end proc:
ans := p();
[edited below]
It is possible to get it a little closer to your original. With procedure p as below the returned result will be one of true/false/FAIL and could be used in a conditional. In the case that the return values if false (because of the response to the initial query) then a second query is made about the choice of another expression.
This version of p takes two arguments, the first is the suggested initial equation. The second is a name which can be assigned any alternative.
restart:
p := proc(candidate, resultvar)
local result, oldprompt, res1, res2;
oldprompt := interface(':-prompt'=``);
try
printf(sprintf("Is the equation you want to use %a? (y/n)\n",
candidate));
res1 := readline(-1);
if member(res1,{"y;","y","yes;","yes"}) then
result := true;
assign(resultvar,candidate);
elif member(res1,{"n;","n","no;","no"}) then
result := false;
printf("Enter your equation.\n");
res2 := readline(-1);
assign(resultvar,parse(res2));
else
printf("Response not recognized\n");
result := FAIL;
end if;
catch:
finally
interface(':-prompt'=oldprompt);
end try;
return result;
end proc:
Now we can test it out.
p(x=f(X0), 'ans');
ans;
We could also use the call to p inside an if statement. Eg,
if p(x=f(X0), 'ans') then
"accepted";
else
"new choice made";
end if;
ans;
Here, answering "n" to the first query will make the conditional test see a false value, but the named argument ans will get assigned to as a side-effect.
Suppose I have a text variable $$string.
How can I write a boolean to check whether $$string contains the text $$substring?
e.g. if $$string is "foobar" and $$substring is "oo", then the result should be True, and if the $$string is "foo" and $$substring is "bar" the result should be False.
For a problem like this I'm partial to the PatternCount function:
PatternCount($$string ; $$substring)
You should then get back false = 0 or true >= 1. You can force true to 1 as follows:
PatternCount($$string ; $$substring) > 0
Function Definition here: http://fmhelp.filemaker.com/fmphelp_10/en/html/func_ref3.33.73.html
Use the Position function:
Position($$string;$$substring;1;1)>0
Note: Position($$string;$$substring;a;b) checks whether $$substring is contained at least b-times in $$string from starting position a, and returns where the b th occurrence is located in $$string, or -1 if there is no b th occurrence. Counting starts from 1.
I'm sorry if this is a 'read the manual' question (I did but can't find an answer).
I have an array of Booleans and I want to test if any of them is true.
model TestArray
(...)
Boolean[:] booleanArray;
Real y;
equation
y = if [if any element in booleanArray is true] then ... else ...;
end TestArray;
How can I do this?
Thanks,
Roel
There are functions like the ones you are requesting in Modelica.Math.BooleanVectors.
Here you'll find allTrue(Boolean b[:]), anyTrue(Boolean b[:]) and oneTrue(Boolean b[:]).
This is an interesting question. Frankly, I'm not aware of any built-in capabilities for doing this (although the need for such capabilities is certainly valid).
What we've frequently done in the past is to write utility functions called "any" and "all", that look like this (untested, but you get the idea):
function any
input Boolean vals[:];
output Boolean result;
algorithm
result := max({if i==true then 1 else 0 for i in vals})==1;
end any;
function all
input Boolean vals[:];
output Boolean result;
algorithm
result := min({if i==true then 1 else 0 for i in vals})==1;
end all;
This is similar to what you did but using array comprehensions and then encapsulating that in functions. This allows you to write code like:
if any(conditions) then ... else ...;
Ideally, these functions could be added to the built-in set of "reduction operators" (like min and max), but the language group tends to be somewhat conservative about introducing such operators because they pollute the namespace and create potential collisions with existing code.
Note that things get a bit tricky when using when clauses. With when clauses, there is a vector construction, e.g.
when {cond1, cond2, cond3} then
...
end when;
Which has very useful semantics, but is not 100% analogous to either "any" or "all" as written above. So if you intend to use a vector of conditions in a when clause, then read up on how this is handled (in the specification) or ask a follow-up question on that and I can elaborate more (it is somewhat beyond the scope of this question).
Section 10.3.4 of Modelica Specification Version 4.3 allows Boolean arrays v as arguments of min(v) and max(v).
If all components of v are true then min(v) gives true, false otherwise.
If all components of v are false then max(v) gives false, true otherwise.
Example model:
model Test
Boolean anyFalseGivesFalse = min( { true, false } );
Boolean allTrueGivesTrue = min( { true, true } );
Boolean allFalseGivesFalse = max( { false, false } );
Boolean anyTrueGivesTrue = max( { false, true } );
end Test;
Now I found a workaround, but it must be possible to do it much nicer:
model TestArray
(...)
Boolean[:] booleanArray;
Real y;
Real[:] test;
equation
for i in 1:size(booleanArray):
test[i] = if booleanArray[i] then 1 else 0;
end for;
y = if sum(test) > 0 then ... else ...;
end TestArray;
You could use Modelica.Blocks.Math.BooleanToInteger to convert your Boolean-array to an Integer-array with which you can calculate ...