We are developing an ABM under AnyLogic 7 and are at the point where we want to make multiple simulations from a single experiment. Different parameters are to be set for each simulation run so as to generate results for a small suite of standard scenarios.
We have an experiment that auto-starts without the need to press the "Run". Subsequent pressing of the Run does increment the experiment counter and reruns the model.
What we'd like is a way to have the auto-run, or single press of Run, launch a loop of simulations. Within that loop would be the programmatic adjustment of the variables linked to passed parameters.
EDIT- One wrinkle is that some parameters are strings. The Optimization or Parameter Variation experiments don't lend themselves to enumerating a set of strings to be be used across a set of simulation runs. You can set a string per parameter for all the simulation runs within one experiment.
We've used the help sample for "Running a Model from Outside Without Presentation Window", to add the auto-run capability to the initial experiment setup block of code. A method to wait for Run 0 to complete, then dispatch Run 1, 2, etc, is needed.
Pointers to tutorial models with such features, or to a snip of code for the experiment's java blocks are much appreciated.
maybe I don't understand your need but this certainly sounds like you'd want to use a "Parameter Variation" experiment. You can specify which parameters should be varied in which steps and running the experiment automatically starts as many simulation runs as needed, all without animation.
hope that helps
As you, I was confronted to this problem. My aim was to use parameter variation with a model and variation were on non numeric data, and I knew the number of runs to start.
Then i succeed in this task with the help of Custom Variation.
Firstly I build an experiment typed as 'multiple run', create my GUI (user was able to select the string values used in each run.
Then, I create a new java class which inherit from the previous 'multiple run' experiment,
In this class (called MyMultipleRunClass) was present:
- overload of the getMaximumIterations method from default experiment to provide to default anylogic callback the correct number of iteration, and idnex was also used to retrieve my parameter value from array,
- implementation of the static method start,
public static void start() {
prepareBeforeExperimentStart_xjal( MyMultipleRunClass.class);
MyMultipleRunClass ex = new MyMultipleRunClass();
ex.setCommandLuneArguments_xjal(null);
ex.setup(null);
}
Then the experiment to run is the 'empty' customExperiment, which automatically start the other Multiple run experiment thru the presented subclass.
Maybe it exists shortest path, but from my point of view anylogic is correctly used (no trick with non exposed interface) and it works as expected.
Related
I am running a parameter variation experiment and would like to be able to stop at a variable value instead of at at specified time. In my simulation I have variable that counts whenever an agent passes through my zink. The variable is called Loads. I would like to stop the parameter variation experiment when Loads=16.
I have tried the "additional experiment stop condition", but can't seem to get it right.
https://imgur.com/a/zD2qTfc
You are mixing up 2 things, I think. You want to stop an individual simulation run when something in the model happens. You can easily do that using this code in your actual model (not in the experiment properties):
if (loads==16) getEngine().stop();
What you did was to define when the parameter variation experiment should stop. However, that condition is never satisfied (and it sounds like you don't want that).
I am trying to change the UVM verbosity of the simulation after satisfying certain conditions. Verbosity options of different components are passing through the command line as +uvm_set_verbosity. Once the conditions are satisfied, then the simulations should run with the the command line +uvm_set_verbosity option. Till then simulation runs with low verbosity for all components.
Looking through the UVM library code, it appears that there is a function called m_set_cl_msg_args(). This function calls three other functions that appear to consume the command line arguments like: +uvm_set_verbosity, +uvm_set_action, +uvm_set_severity.
So what I did was get the uvm_root instance from the uvm_coreservice singleton, and then use the get_children() function from uvm_component class to recursively get a queue of all of the uvm_components in the simulation. Then call the m_set_cl_msg_args() function on all of the components.
My code looks like:
begin
uvm_root r;
uvm_coreservice_t cs_t;
uvm_component array_uvm[$];
cs_t = uvm_coreservice_t::get();
r = cs_t.get_root();
r.get_children(array_uvm);
foreach(array_uvm[i])
array_uvm[i].m_set_cl_msg_args();
end
Even though this code compiles properly, But this is not changing verbosity. Any idea ?
Moreover I am able to print all the components in array_uvm. So I am guessing
array_uvm[i].m_set_cl_msg_args();
this as a wrong call.
Anyone have any other suggestion to change verbosity during run time.
You should never use functions in the UVM that are not documented in the language reference manual. They can (and do) change in any revision. I'm guessing +uvm_set_verbosity only works at time 0 by default.
There is already a function to do what you want
umm_top.set_report_verbosity_level_hier()
I suggest using +UVM_VERBOSITY=UVM_LOW to start your test, and then define your own switch for activating the conditional setting.
If you want a specific component, use component_h.set_report_verbosity_level() (add the _hier to set all its children)
You can use the UVM's command line processor get_arg_values() method to specify the name of the component(s) you want to set, and then use umm_top.find() to get a handle to the component.
the basic idea behind the modeling issue is a breakdown of a production machine.
I would like to model this by setting the arrival rate (simply arrivals per second) to zero (Source.rate = 0). After the machine is repaired, the arrival rate is set to its actual value again (e.g., Source.rate = 5). While the first command does the job, the second does not seem to have any effect, i.e. new agents are not created.
The segment of the model is rather simple: Source --> Select Output (decision about breakdown) --> true: go on in production; false: delay (repair machine) --> go on in production.
Source.rate = 0 is called at the out port (false) of "breakdown" and Source.rate = 5 at the out port of "repair".
https://i.stack.imgur.com/hqGoI.png
Of cause, this issue might be modeled differently (e.g., using hold with disabled "forced pushing"), however, it is not clear for me why my approach does not work.
Thanks in advance!
Instead of using source.rate=5; use source.set_rate(5);
To expand on Felipe's answer with an explanation:
Instead of using source.rate=5; use source.set_rate(5);
rate is effectively a Parameter (in the AnyLogic sense) of the Source block. (All AnyLogic's Process Modeling blocks are actually themselves Agents developed by AnyLogic, and thus with Parameters, Variables, etc.)
You can set an AnyLogic Parameter directly (via just assigning a value as you did), but they also all have a set_<parameter name> method (function) which should really always be used instead because this triggers any internal on-change logic for this Parameter. It is only this triggered logic (internal to the Source block) which causes the Source to 're-evaluate' the rate properly.
(You can use on-change logic for Parameters in your own models, and need to do so when altering a parameter requires some 'adjustments' to the rest of the model; i.e., in situations where the change doesn't 'just work' due to other bits of the model reading the new value after the change point.)
I don't know why your model doesn't work (maybe more details of your model is needed), but a simple solution which I tested and worked, is as below:
You can set the source's "Type of arrival" to "calls of inject() function", add an event to your model and set its "Trigger type" to "Rate" and set its rate value to 5. Then in action code of the event use below code:
if(yourCondition)
{
source.inject(1);
}
I hope it helps you.
For the use case of being able to abort parallel simulations with a MATLAB GUI, I would like to stop all scheduled simulations after the user pressed the Stop button.
All simulations are submitted at once using the parsim command, hence something like a callback to my GUI variables (App Designer) would be the most preferable solution.
Approaches I have considered but were not exactly providing a desirable solution:
The Simulation Manager provides the functionality to close simulations using its own interface. If I only had the code its Stop button executes...
parsim uses the Simulink.SimulationInput class as input to run simulations, allowing to modify the preSimFcn at the beginning of each simulation. I have not found a way to "skip" the simulation at its initialization phase apart from intentionally throwing an error so far.
Thank you for your help!
Update 1: Using the preSimFcn to set the the termination time equal to the start time drastically reduces simulation time. But since the first step still is computed there has to be a better solution.
simin = simin.setModelParameter('StopTime',get_param(mdl,'StartTime'))
Update 2: Intentionally throwing an error executing the preSimFcn, for example by setting it to
simin = simin.setModelParameter('SimulationCommand','stop')
provides the shortest termination times for me so far. Though, it requires catching and identifying the error in the ErrorMessageof the Simulink.SimulationOutput object. As this is exactly the "ugly" implementation I wanted to avoid, the issue is still active.
If you are using 17b or later, parsim provides an option to 'RunInBackground'. It returns an array of Future objects.
F = parsim(in, 'RunInBackground', 'on')
Please note that is only available for parallel simulations. The Simulink.Simulation.Future object F provides a cancel method which will terminate the simulation. You can use the fetchOutputs methods to fetch the output from the simulation.
F.cancel();
I am looking to set up a test set for an existing Simulink model. Ideally I could take full control of the model, explicitly stepping it and measuring the state of any signal on any bus in the model.
As might have been gleaned, this is the precursor of a unit testing system for the model. Being so, I can't really justify changing the model to suit the test, the test must accommodate the model as-is.
The furthest I've got so far is using load_model() to return a handle to the model. From there there seems to be a quite obscure set of functions for accessing the model. I can't see any that relate to accessing states and can't see any further commands that relate to accessing a loaded model.
The easiest way is to use the Data Import/Export function within the Simulink Preferences.
Set the checkbox States and it will store every state of your system for every time step in your workspace, also when you pause the simulation or execute it step by step.
Be aware not to set Save simulation output as single object, in this case the access would be more complicated and you need to follow the instructions here.
To add to the other answer, you probably want to check this page in the documentation: Control Simulation Using the set_param Command. Of interest are the following commands:
set_param(<model_name>, 'SimulationCommand', 'start')
set_param(<model_name>, 'SimulationCommand', 'pause')
set_param(<model_name>, 'SimulationCommand', 'WriteDataLogs')
set_param(<model_name>, 'SimulationCommand', 'continue')
Replace <model_name> by the path to your model file.