Is there a possibility to set the start and stop date of an simulation run using a function or parameter?
Thanks for helping!
There is. These functions can be accessed via the Engine object. You can find the documentation of the class here. The functions you are looking for are:
setStartDate(java.util.Date date)
setStartTime(double tstart)
setStopDate(java.util.Date date)
setStopTime(double tstop)
Either in the Experiment or in the Main of your model, you can use (as an example) this code:
getEngine().setStartTime(100);
Of course, once the model is already started, only setting of stop time/date will have an effect.
Related
Is there an easy way to figure out all places where a variable or parameter is being utilised in annylogic. Trying to locate where each variable is used can be a pain during debugging.
Sure. Just "ignore" it in the properties and compile the model.
You will get a list of errors for all places where it is called. Double-click on each error and AnyLogic even takes you there :)
Else, you can also use the AnyLogic search functionality.
in order to get some relief for that pain if your model is too big, all your variables should be private and you create setters, so each time you change your variable, you required to use a set function.
This doesn't solve your question, but it tells you what to do in future models to make it easier for you
check this video
https://www.youtube.com/watch?v=gNBfdB6YF7o
Context: I have a huge Simulink Model that is going to be used for automated simulations on a Debian 10. Therefore it has to be built as standalone C-Code using the Matlab Coder. This code is then called to start the simulation.
What I need: I need to find a way to initialize my built model with ~500 parameters. These change with each simulation run and are stored in a SQLite file. The goal is to have parameters written to the database, then start the Model which reads the parameters from SQLite during initialization (presumably using the InitFcn Model Callback, although I'm open to alternatives).
What I have tried:
Direct SQL interface: I tried to use a direct Matlab-SQL interface such as JDBC (since I don't have access to the Database-toolbox) but those are not supported for Code generation.
Write a C-function that reads the SQLite file, then call the function during initialization in the InitFcn Callback using coder.ceval like this:
data = 0;
err = coder.ceval('read_function',4, 2, 12, coder.wref(data));
parameter = data;
Problem here is that coder.wref is not supported in Matlab and therefore doesn't work in the InitFcn. (Please correct me if I'm wrong)
This only seems to work inside a Matlab-Function-Block:
Error evaluating 'InitFcn' callback of block_diagram 'Model'.
Caused by:
The coder.wref function is not supported in MATLAB.
So my problem with the second approach is, that I can't call the C-function during initialization.
Using a Matlab-function-Block to read the parameters isn't really an option, since I would have to route all the signals out which makes maintaining and further development of the model really hard. Also my suggestion is, that the model would not even run because the parameters are needed to initialize the model.
Questions:
Is there a way to make one of the above approaches work? If yes, how? Where is my mistake?
Is there another (simpler) option to pass the data as an array or struct to my model?
Database looks like this:
Identifier Default
latitude 52.5
longitude 13.4
electricity_consumption 4000.0
ventilation_stream 50.0
PV_peak 30.0
PV_orientation 0.0
no_vessels 28.0
heatpump_exists 1.0
hotwater_consumption 1000.0
.
.
.
After having spent so much time on this issue, I would like to share my experience on this problem:
SQLite: This approach did not work out for me because the direct SQL-Matlab interfaces are not supported for code generation.
It is in fact possible to write a C-function, that reads from SQLite and call that function in a Matlab-function-block via coder.ceval wich allows to read in a signal during simulation. This works for code generation (Simulink coder) as well. However this will not work for initialization (see question).
So none of my original approaches ended up working.
Workaround: I ended up switching to an approach based on the Simulink RSIM-target wich generates code (also for Linux) and can be parametrized via a .mat file wich contains all the parameters. The .mat file can be modified to update parameters. This required some additional code wich automates this step. Also the model configuration for RSIM is a bit tricky.
In the simulation window, before the run, I'd like to change some probability distributions (e.g. delay time) by typing, for example, "triangular(5, 20, 15)" into a specific editbox linked to a variable.
I know how to do this with static values, but I couldn't figure out how to do the same with probability distributions.
AnyLogic offers a built-in functionality for that with com.anylogic.engine.database.CodeValue.
It is originally meant that a distribution function stored as text in the internal database can be parsed to java code and executed, but it actually also works without the database and for any kind of code. It is the same idea as in Benjamin's answer, just that you do not need to add any external java library.
Use it like this:
CodeValue myCode = new CodeValue(this,"....java code to be executed");
myCode.execute();
And in your specific case, assuming you have a variable named variableA and an editbox named editbox, use the following to evaluate the expression, get a value and set it for the variable:
CodeValue myCode = new CodeValue(this,"variableA = "+editbox.getText());
myCode.execute();
Obviously, allowing the user to type any command there and running it without a check or error treatment is a bad idea, be aware of that.
This is a Java issue. You need to convert a String (your editbox content) to executable code. Not straight-forward but also not impossible, see Convert String to Code and similar posts.
So, I'm pretty new with Anylogic, but have done a lot of tutorials and I have programming experience in Java. For my thesis I'm modelling a vehicle flow as a process. In the source block, I create custom agents (vehicles) with some parameters from the database. This works fine. Then I want to assign an electric parameter with randomTrue(0.5). For this, I call a setupTaxi-function, where electric ist set. The parameter for the randomTrue-function should be changeable, so I set it as an extra paramter anteilEtaxis (0.5).
After that, I want the vehicles to do different things depending on the value of electric using SelectOutput. I selected the Condition and test on agent.electric.
I basically did the exact same thing as described in the Anylogic help. And yet the framework always chooses the true Output port, no matter if the parameter ist set to true or false.
See the image for setup and parameters. I tested this via console (the first line is a println-call in source, the second a println-call in selectOutput.). Plus you can see that the parameter is set to different values, because the 3D visualisation model depends on it:
enter image description here
Also, I tried a few different combinations of setting the parameters, reading them etc... The only thing that will work is putting randomTrue(0.5) directly in the Condition box. This is not what I want though. So if you have an idea, what is wrong, please tell me.
This is a typical beginners problem.
I will assume you are calling the setupTaxi-function in your source in the "on exit" action... If you are doing that, then it's too late and the agent already made its decision on where it will go after the select output block.
You have to call your setupTaxi-function in 2 possible places:
1) In your source on the "on at exit" action
2) In your vehicle agent on the "on startup" action
Or even.. just make electric variable have a default value of randomTrue(main.anteilEtaxis)... that will also work.
This is the problem:
Create a class and set the access to be private for some of the properties or methods.
Use the doc command for the created class. This will auto-generate documentation from your comments and show it in the built-in help browser.
doc classname
The problem is that documentation for the private properties and methods is not shown in the help browser. Is there any way to overcome this problem?
So I spent like 10 minutes using the debugger, jumping from one function to the next, tracing the execution path of a simple doc MyClass call.
Eventually it lead me to the following file:
fullfile(toolboxdir('matlab'),'helptools','+helpUtils','isAccessible.m')
This function is called during the process of generating documentation for a class to determine if the class elements (including methods, properties, and events) are publicly accessible and non-hidden. This information is used later on to "cull" the elements.
So if you are willing to modify MATLAB's internal functions, and you want the docs to always show all methods and properties regardless of their scope, just rewrite the function to say:
function b = isAccessible(classElement, elementKeyword)
b = true;
return
% ... some more code we'll never reach!
end
Of course, don't forget to make a backup of the file in case you changed your mind later :)
(on recent Windows, you'll need to perform this step with administrative privileges)
As a test, take the sample class defined in this page and run doc someClass. The result:
This behaviour is by design - the auto-generated documentation is intended for users of the class, who would only be able to access the public properties and methods.
There's no way that I'm aware of to change this behaviour.
You could try:
Use an alternative system of auto-generating documentation such as this from the MATLAB Central File Exchange (which I believe will document all properties, not just public).
Implement your own doc command. Your doc command should accept exactly the same inputs as the built-in doc command, detect if its inputs correspond to your class/methods/properties etc, and if so display their documentation, otherwise pass its inputs straight through to the built-in doc. Make sure your command is ahead of the built-in on the path.