Is there a way to change the value of "Maximum number of event iterations" ,eviter, that is set to 20 in dymola?
It seems like dymosim.ini is not used for regular simulations (Note the version in line 4: dymosim.ini states 1.1, whereas the dsin.txt has 1.4 written in Dymola 2019). I also could not find a function or variable in Dymola to change eviter, so the only solution I can think of is to edit dsin.txt before simulation.
The code below shows how a function could look like which updates dsin.txt and then performs a simulation. Note that the function should be extended for error handling.
function MySim
import Modelica.Utilities.Strings;
import Modelica.Utilities.Streams;
import Modelica.Utilities.Files.removeFile;
import SimAPI = DymolaCommands.SimulatorAPI;
input String m = "Modelica.Blocks.Examples.PID_Controller"
annotation (Dialog(__Dymola_translatedModel(translate=false)));
input Integer iterations = 40;
protected
String[:] dsin;
algorithm
// initialize
removeFile("dsin_custom.txt");
removeFile("dsin_export.txt");
SimAPI.translateModel(m);
SimAPI.exportInitialDsin("dsin_export.txt"); // exports simulation setup of active model
// write custom dsin file
dsin :=Streams.readFile("dsin_export.txt");
for i in 1:size(dsin, 1) loop
if Strings.find(dsin[i], " # eviter ") > 0 then
dsin[i] :=Strings.replace(dsin[i], "20", String(iterations));
break;
end if;
end for;
for i in 1:size(dsin, 1) loop
Streams.print(dsin[i], "dsin_custom.txt");
end for;
// simulate and open file
// using simulateModel would generate a new dsin file, so dymosim.exe must be called
SimAPI.system("dymosim.exe -s dsin_custom.txt "+m+".mat");
// workaround: create empty plot to open result, as there is no load-result command
DymolaCommands.Plot.createPlot(y={""}, grid=true, filename=m+".mat");
end MySim;
The function translates the selected model, exports the simulation setup, edits it as needed, performs the simulation and opens the result file - so it is basically a customized simulateModel-command.
With the features described in 7.2 Extendable user interface – menus, toolbars and favorites in the Dymola User Manual Volume 2 a shortcut to the function can be created in the Dymola GUI, which allows to perform the simulation for the selected model. This would make the function as convenient to use as the regular simulate button.
Since Dymola 2020x there is an advanced variable that should do exactly that.
From the 2020x changelog:
Advanced.Simulation.MaxEventIterations The maximum number of evnet
iterations, eviter. Use with care, since too small value will lead to simulation failure.
The default value is Advanced.Simulation.MaxEventIterations=20
Additionally the precision for the iteration can be changed:
Advanced.Simulation.EventEpsilon The time resolution for events, eveps. The
default value is Advanced.Simulation.EventEpsilon=1e-10
Related
The random value is coming out to be different even when randomSeed() is initialised inside the setup() method.
For example:
function setup() {
createCanvas(400, 400);
randomSeed(400);
console.log(random(100));
}
function draw() {
console.log(random(100));
check();
noLoop();
}
function check(){
console.log(random(100));
}
Here, the three functions are giving different random values. Similarly, if I have a couple of functions like funcA, funcB, funcC etc, how to get a same random value throughout the program?
Similarly, if I am using noise() function, is there a way to get the same noise value every time the program is run when I am adding noiseSeed() in the setup() function?
What do you mean by "The random value is coming out to be different"?
If you mean, that each call to random(100) results in a different value, that is the expected behavior!
Each call to random(100) results in a random value, but if you restart the program, you will get the same values again.
For me, your program results in
39.10889436956495
56.007297383621335
70.2842695871368
Every single time I run it.
If you remove randomSeed(400);, every time you start the program, the values will be different.
If you want random(100) to always return the same value, don't use the function, just replace it with the value you want.
But if by "The random value is coming out to be different" you mean, that running the program multiple times will result in different output for you, then something is broken in your setup.
I've a fairly simple program which needs user input in the form of a text string. I've a CLR form with an edit box and I need to take that input and pass it into my class which just copies it to a member variable.
In the Form.h code, handling the TextChanged event is...
int textLength = m_userDest->TextLength;
if (textLength > 2 && textLength < 5)
{
// Could be an ICAO code in here
char dest[5];
String^ text = m_userDest->Text->ToUpper();
sprintf_s(dest, 5, "%s", text);
airTraffic.SetUserDest(dest);
}
My class (airTraffic) SetUserDest function is just
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
When this is run I get this debug assertion, it doesn't stay on the screen and automatically clears after a few seconds.
Debug Assertion Failed!
Program: ...sual Studio 2010\Projects\FSAirTraffic\Debug\FSAirTraffic.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\tcsncpy_s.inl
Line: 24
Expression: ((_Dst)) != NULL && ((_SizeInBytes)) > 0
I don't have an f:\ drive so I'm guessing this is some internal Microsoft(?) code so I can't see the context of the assertion and exactly what it's problem is. I don't have a file called tcsncpy_s.inl on my machine.
If I don't call my class function then there's no assertion so I assumed that was the problem.
Curiously though, when stepping through the debugger the assertion occurs as I step out of the TextChanged event, with the rest of the functions operating as intended (as far as I can see).
Does anyone know what the problem is and how I can go about solving it?
I don't understand how your code works. You use m_userDest twice, first it appears to be a pointer to a structure of some sort, maybe a handle to a TextBox control:
int textLength = m_userDest->TextLength;
Later you pass it to strncpy_s, which needs a char*, not a pointer to some structure.
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
While it's possible for a structure to implicitly convert to a char*, it's not possible for a structure pointer to do so. Perhaps there's a smart pointer involved? Or you are using the same member variable name for completely different purposes in different classes1?
In any case, strncpy_s is inspecting the value of its first argument and not liking it.
1 Note that the new "wisdom" saying not to use Hungarian notation has destroyed the ability to understand this code in textual form. We don't have an IDE providing mouseover information about the data type of variables. Applications Hungarian is still a good idea in the real world, despite how many "best practices" documents decry it. Amazing how many code style documents are written from a purely theoretical basis.
I am using a non-scalar parameter for my parameter study:
*.server.serviceTime = ${B=exponential(20ms), exponential(35ms)}
However, compared to the other scalar parameters, the B parameter is not shown in the Browse Data section of the results, which I was using until now to export the results of my parameter study:
How can I record the parameter of the exponential distribution (B) that I'm using?
The serviceTime is declared in the .ned as follows:
volatile double serviceTime #unit(s);
If I'm not mistaken you would like to record the mean value of the exponential distribution. Here is an example how the PureAlohaExperiment sample does this:
[Config PureAlohaExperiment]
...
Aloha.numHosts = ${numHosts=10,15,20}
Aloha.host[*].iaTime = exponential(${mean=1,2,3,4,5..9 step 2}s)
i.e. put the interation variable inside the exponential function.
You may put in a NED module a parameter called B. Then, you do the following in the omnetpp.ini:
**.B = ${B=exponential(20ms), exponential(35ms)}
Finally, you record the B NED parameter in the finish() function:
recordScalar("B", par("B"));
There is an option param-record-as-scalar for saving parameter as a scalar. An example of using it:
*.server.serviceTime.param-record-as-scalar = true
However, it doesn't work for volatile parameters (there is an error during finishing simulation). It seems that it is intentionally behaviour to avoid registering "meaningless" random values.
If you really need current random value of volatile parameter, you should record it as a new scalar just after reading it, for example:
double serviceTime = par("serviceTime").doubleValue();
recordScalar("serviceTime 1", serviceTime);
// ... later
serviceTime = par("serviceTime").doubleValue();
recordScalar("serviceTime 2", serviceTime);
I have a treeview and want to get notified if the selection changes. What is the signature for the callback?
I found a code snippet like:
Gtk::TreeView *treeview = Gtk::manage(new Gtk::TreeView);
Glib::RefPtr< Gtk::TreeSelection > sel = treeview->get_selection();
sel->set_mode( Gtk::SELECTION_MULTIPLE );
sel->set_select_function(sigc::ptr_fun(&SelFun));
But I can't find anything about the SelFun!
How is the signature
How to find out which rows and columns are selected inside this function?
How to access data from the model with that object
Yes, I have actually no idea how the TreeView/Model/Path/Selection interacts. Every link to an example is highly welcome!
You seem to want multiple selection. I had the same problem too. Once you have enabled mutliple selection, getting the selected rows is a little more difficult. The method of acquiring them varies slightly.
I'll provide the most general method. First, you need to overload the signal_changed() signal after you have enabled multiple selection. Then, assign the TreeView's TreeSelection to a RefPtr for easy access.
Glib::RefPtr<Gtk::TreeSelection> TreeView_TreeSelection;
TreeView_TreeSelection = your_TreeView.get_selection();
Next, connect the TreeSelection to the signal_changed() signal.
TreeView_TreeSelection -> signal_changed().connect(sigc::mem_fun(your_TreeView,
&your_Class::on_selection_changed));
Now, make sure to make a void function header in "your_Class" named on_selction_changed() or whatever you want. Just make sure to change the name in the connection above to whatever your class' name is.
The final step is to make the function. Here is a simple example of getting a vector of all of the TreePaths of the rows selected, then converting those TreePaths into a vector of TreeModel::Row pointers.
void your_Class::on_selection_changed()
{
if((TreeView_TreeSelection -> count_selected_rows()) == 0)
{
return;
}
vector<Gtk::TreeModel::Path> selected_rows = TreeView_TreeSelection -> get_selected_rows();
vector<Gtk::TreeModel::Row*> selected_TreeRows;
vector<Gtk::TreeModel::Path>::iterator TreePath_iterator = selected_rows.begin();
Gtk::TreeRow *row;
while(TreePath_iterator != selected_rows.end()
{
selected_row_it = p_TreeModel -> get_iter(TreePath_iterator);
row = (*selected_row_it);
selected_TreeRows.push_back(row);
TreePath_iterator++;
}
}
Do you know how to iterate through a TreeModel using the STL-like contain API called children() of a TreeModel? It's most useful for iterating over all of the rows of a TreeModel or getting the size (AKA row count) of a TreeModel. Its use depends on whether you're using a ListStore, TreeStore or a custom TreeModel.
In SuperCollider: How do I downsample a control rate variable to a scalar value?
For instance, I have a scalar global called ~delay and a few functions care about that value. They assume it is a scalar. I wanted to set a envelope generator on that variable in order to change it via a control rate variable. Or use MouseX.kr, if I could convert a single value of MouseX.kr to a scalar value I would be happy.
Assume that I cannot refactor the code to allow for a k-rate global and thus I need to sample or downsample a single value from a control rate variable.
I can't do this:
MouseX.kr(1, 4, 1).rand.wait;
But I'd be happy with this:
downSample(MouseX.kr(1, 4, 1)).rand.wait;
Or
~mousex = MouseX.kr(1, 4, 1)
...
downSample(~mousex).rand.wait
This is the classic SuperCollider language-vs-server issue. You want to use MouseX (which represents the server's knowledge of mouse position) in a language-side calculation. ("Why the split? Why can't the language know it using the same object?" - well, imagine the two processes are running on different machines - different mice...)
To get the mouse position in the language, it's better to use one of:
Platform.getMouseCoords // SC up to 3.6
GUI.cursorPosition // SC recent versions
If you're sure you want to use server data in the language, then your own answer about sending via a Bus is one way to do it. Recent versions of SuperCollider have methods
Bus.getSynchronous
Bus.setSynchronous
which rely on the new "shared memory interface" between language and server. If the two are on the same machine, then this can be a nice way to do it which avoids the latency of asynchronously requesting the info.
After much research I came up with 1 solution: use a control Bus to grab values. We take a function as input (f) and then play it to a bus.
We then read from that bus by calling the get method on the bus and providing function that allows us to extract the value from the function thrown in.
~mkscalarfun = {
arg f={ 0 };
var last = 0.0;
var mbus = Bus.control(s, 1);
var pf = f.play(s,mbus);
var scalarf = {
mbus.get({|v| last = v;});
last;
};
scalarf; // This is a function
};
// Create a closure that includes the bus
~mousescalarf = ~mkscalarfun.({ MouseX.kr(1, 4, 1); });
~mousescalarf.();
~mousescalarf.().rand.wait;
I am not sure how idiomatic this solution or if it is appropriate or how well it performs.
One problem with this solution is that pf is hidden and thus you can't stop it.
One alternative is to use an OO solution where you make a class in your extension directory:
MakeScalarKR {
var last;
var mbus;
var pf;
var f;
*new { arg sbase,f;
^super.new.init(sbase,f)
}
init {
arg sbase,myf;
f = myf;
last = 0.0;
mbus = Bus.control(sbase, 1);
pf = f.play(sbase, mbus);
}
v {
mbus.get({|x| last=x;});
^last
}
free {
pf.free
}
}
Then you can invoke this class like so:
~mkr = MakeScalarKR(s,{ MouseX.kr(10,400,1) });
~mkr.v()