OpenModelica / OpenModelica

OpenModelica is an open-source Modelica-based modeling and simulation environment intended for industrial and academic usage.
https://openmodelica.org
Other
818 stars 304 forks source link

Allow for modifiers in buildModel, translateModel() and simulate() API functions #2174

Open OpenModelica-TracImporter opened 4 years ago

mwetter commented 1 year ago

Is there a way to set parameter values in translateModel? Such as for example

translateModel("MyModelicaLibrary.MyModel(p=1)", method="dassl", tolerance=1e-08)

where p is a parameter in MyModel? The reason for my question is that I am writing a simulator class for OpenModelica in BuildingsPy with an API similar to https://simulationresearch.lbl.gov/modelica/buildingspy/simulate_Dymola.html#buildingspy.simulate.Dymola.Simulator.addParameters If I understand it right, the above is not possible, unless one creates first a new Modelica model that extends MyModel, sets the parameters in the extend clause, and then the new model would need to be translated and simulated.

adrpo commented 1 year ago

We should implement this, is not that complicated. Basically one can do this with OpenModelica:

loadString("model MyModel extends MyModelicaLibrary.MyModel(p=1); end MyModel");
buildModel(MyModel, method="dassl", tolerance=1e-08); // translateModel does not generate the executable, just the C code
casella commented 1 year ago

@mwetter, if you just want to modify a parameter which is not structural and is evaluated at runtime, you can use the -override simulation flag. This saves you the time to recompile every time you change the value.

However, if for some reason the parameter is evaluated at compile time, I'm afraid this would silently fail, e.g. the parameter is not modified and you get no feedback. I'm not 100%, you may check this with some simple example like

model M
  parameter Real p = 10 annotation(Evaluate = true);
  Real x = p*time;
end M;
casella commented 1 year ago

@perost, if you don't see any major problem with @adrpo's proposal, would you mind implementing it in the API?

perost commented 1 year ago

You can set a modifier by doing:

setComponentModifierValue(MyModelicaLibrary.MyModel, p, $Code(=1));

However, this will modify the loaded model so if you want to e.g. translate the same model multiple times with different modifiers you might need to reload it between.

As for adding modifiers to the API I guess we could add a separate argument similar to setComponentModifierValue for passing a modifier. But we have a lot of API functions which translate models in some way, and if we want to be consistent we'd have to add it to all of them which would be quite a lot of work.

adrpo commented 1 year ago

I guess we could just extend Absyn.C_TYPENAME and the grammar to include the modifiers. But we would need to be careful on what and how we cache if several different models with the same path can possibly exist at the same time.

mwetter commented 1 year ago

My use case involves structural parameters. The issue with

loadString("model MyModel extends MyModelicaLibrary.MyModel(p=1); end MyModel;");

is that then the files generated by translation and simulation will by MyModel* and no longer MyModelicaLibrary.MyModel* This is doable but adds a level of complexity to make sure names are unique if two different models (MyModelicaLibrary.MyModel1 and MyModelicaLibrary.MyModel1) are simulated and to rename files back again at the end of the process (which then break links in error messages or warnings as they would be referring to MyModel).

adrpo commented 1 year ago

I think you can do buildModel(MyModel, fileNamePrefix="MyModelicaLibrary.MyModel") to get the name you want (I am on my phone now so I cannot check). As for error messages, I doubt you will have errors in MyModel as that one is just one extends, all the errors should point to MyModelicaLibrary.MyModel.

mwetter commented 1 year ago

@adrpo : Thanks, using buildModel works.

casella commented 1 year ago

So, summing up, the easiest way to get

buildModel("MyModelicaLibrary.MyModel(p=1)", method="dassl", tolerance=1e-08)

is to do

loadString("model ModifiedModel extends MyModelicaLibrary.MyModel(p=1); end MyModel");
buildModel(MyModel, fileNamePrefix="MyModelicaLibrary.MyModel, method="dassl", tolerance=1e-08); 

As for error messages, I doubt you will have errors in MyModel as that one is just one extends, all the errors should point to MyModelicaLibrary.MyModel.I wrote ModifiedModel because

True, except you could have typed the wrong modifiers 😅. I propose to call MyModel ModifiedModel instead, so in case there are errors with the modifiers, they will be referred to ModifiedModel, which is hopefully clear enough.

We should implement the one-line syntax above in the the API for buildModel(), translateMode(), simulate(), and linearize().

@perost, @adrpo what do you think?