Division by zero depending on parameter - modelica

I am using the FixedRotation component and get a division by zero error. This happens in a translated expression of the form
var = nominator/fixedRotation.R_rel_inv.T[1,3]
because T[1,3] is 0 for the chosen parameters:
n={0,1,0}
angle=180 deg.
It seems that Openmodelica keeps the symbolic variable and tries to be generic but in this case this leads to division by zero because it chooses to put T[1,3] in the denominator.
What are the modifications in order to tell the compiler that the evaluated values T[1,3] for the compilation shall be considered as if the values were hard coded? R_rel is internally in fixedRotation not defined with Evaluate=true...
Should I use custom version of this block? (when I copy paste the source code to a new model and set the parameters R_rel and R_rel_inv to Evalute=true then the simulation works without division by zero)...
BUT is there a modifier to tell from outside that a parameter shall be Evaluate=true without the need to make a new model?
Any other way to prevent division by zero?

Try propagating the parameter at a higher level and setting annotation(Evaluate=true) on this.
For example:
model A
parameter Real a=1;
end A;
model B
parameter Real aPropagated = 2 annotation(Evaluate=true);
A Ainstance(a=aPropagated);
end B;

I don't understand how the Evaluate annotation should help here. The denominator is obviously zero and this is what shall be in fact treated.
To solve division by zero, there are various possibilities (e.g. to set a particular value for that case or to define a small offset to denominator, you can find examples in the Modelica Standard Library). You can also consider the physical meaning of the equation and handle this accordingly.
Since the denominator depends on a parameter, you can also set an assert() to warn the user there is wrong parameter value.
Btw. R_rel_inv is protected and shall, thus, not be used. Use R_rel instead. Also, to deal with rotation matrices, usage of functions from Modelica.Mechanics.MultiBody.Frames is a preferrable way.
And: to use custom version or own implementation depends on your preferences. Custom version is maintained by the comunity, own version is in your hands.

Related

Coupled variables in hyperparameter optimization in MATLAB

I would like to find optimal hyperparamters for a specific function, I am using bayesopt routine in MATLAB.
I can set the variables to optimize like the following:
a = optimizableVariable('a',[0,1],'Type','integer');
But I have coupled variables, i.e, variables whose value depend on the existence of other variables, e.g., a={0,1}, b={0,1} iff a=1.
Meaning that b has an influence on the function if a==1.
I thought about creating a unique variables that encompasses all the possibilities, i.e., c=1 if a=0, c=2 if a=1,b=0, c=3 if a=1,b=0. The problem is that I am interested in optimizing continuous variables and the above approach does not hold anymore.
I tried something alone the line of
b = a * optimizableVariable('b',[0,1],'Type','integer');
But MATLAB threw an error.
Undefined operator '*' for input arguments of type 'optimizableVariable'.
After three months almost to the day, buried deep down in MATLAB documentation, the answer was to use constrained variables.
https://www.mathworks.com/help/stats/constraints-in-bayesian-optimization.html#bvaw2ar

Forcing a member of a struct

I am trying to force some internal nodes in my design. One thing I am trying to force is a member of a struct.
When I try to do this:
module struct_force;
struct {
logic a;
logic b;
logic c;} d;
initial begin
force d.a = 1;
$display(d);
end
endmodule
Incisive gives me an error:
Illegal use of a bit-select, part-select, member-select or mda element [9.3.1(IEEE)]
But VCS appears to be happy with it: See EDA playground example
From IEEE-1800 I see this related to force:
The left-hand side of the assignment can be a reference to a singular
variable, a net, a constant bit-select of a vector net, a constant
part-select of a vector net, or a concatenation of these.
I am having trouble parsing that sentence to figure out who is wrong: Is Incisive preventing me from doing something I should be able to do, or is VCS playing fast and loose with the spec?
If this is in fact illegal, what is work around to force just part of a struct?
The key term in the above sentence is singular variable. The variable you are trying to force is an unpacked struct, which is not a singular variable; it is an aggregate variable.
And if you turn it into a packed struct, you run into the sentence that follows the one you quoted: "It shall not be a bit-select or a part-select of a variable..."
Nets are effectively broken down into individual scalar bits whose value is a resolution function of the drivers of that net. A force becomes just another driver of that net.
It's not impossible to add this as an enhancement to the LRM, but a tool would have to break the variable up into individual bits - every regular assignment to that variable would have to be done bit-by bit to check if one of the bits was in a forced state.

Detecting change in RealInput variable in Dymola

I need to detect whenever there is a change in a RealInput value X. I habe tried to check
if X == pre(X), but only receive an error and a warning that Real cannot be compared for equality. I also thought about using the derivative of X, but there is no explicit expression for this.
Other thoughts of mine have been to try to sample the continuous input into discrete variables that I can compare. Could this work in some way?
Try the change() operator. It is described in $3.7.3.1 of the Modelica Specification. According to the specification, it will be expanded to X<>pre(X), so that might work as well.
The change() operator is only practically useful for non-Real signals. The reason is that <> is not defined for Real types. Instead, you'll need to create a model that checks to see whether the signal deviates from the last recorded value by more than a given "epsilon". I haven't tested it, but the code would look something like this:
model DetectChange
parameter Real eps;
input Real signal;
output Boolean change;
protected
Real last_value;
initial algorithm
last_value = signal;
algorithm
when pre(change) then
last_value := signal;
end when;
change := abs(signal-last_value)>=eps;
end DetectChange;
Again, I haven't tested this. But it gives you some idea.

how to minimize a function under Anneal method with bounds?

I am trying to minimize a function with method = 'Anneal'
I have specified the bounds in a dictionary called opts with 'lower': 0.0 and 'upper': 1.0
I pass opts in the options argument.
The optimization works and I get an answer.
However the values of the best solution are above the upper bound set by me.
Any idea what I am doing wrong? Should bounds be set in any other way?
If you are requiring an optimizer that respects bounds specifications and that do not require derivatives:
scipy contains fmin_cobyla that supports any type of constraints and does not require derivatives. It is not a global optimizer (but on the other hand I don't believe simulated annealing can guarantee global optimzality either).
NLOpt has a Python interface and contains the more efficient BOBYQA algorithm for nonlinear optimization with variable bounds.

Choosing MATLAB Vector element based on Simulink model argument

I'm trying to parameterize one of my Simulink models, so that I will have a gain in the model whose value is equal to an element of a MATLAB workspace vector indexed by the model parameter. That is, I want to define a model argument WheelIndex and have a gain inside the model with a value AxelLoads(WheelIndex).
When I do it exactly as I've described above, I get "vector indices must be real and positive integers" error. When I change the model argument to AxelLoad(To be used directly in the gain component) and assign its value to be AxelLoads(1)(for the first wheel) I get:
Error in 'Overview/Wheel1'. Parameter '18000.0, 15000.0, 17000.0,
21000.0' setting: "18000.0, 15000.0, 17000.0, 21000.0" cannot be evaluated.
I've also tried importing the vector as a constant block into the model, and use a selector block parameterized by the WheelIndex argument to direct the right element to a multiplication block (thereby making an ugly gain block), but then Simulink complains that I'm trying to use a model argument to define an "un-tunable value".
I just want to somehow define the parameters in the MATLAB workspace to be used in each model instance, so that I can, say, calculate the total weight by adding the loads on each wheel. Simulink seems to block all workarounds I've been trying.
Thanks
Could you use a lookup table to obtain AxelLoads vs. WheelIndex?
The easiest way is if I just came over? :P
Perhaps this explaination of tunable parameters helps a little?