Intro

For a while I have been using Salome to create finite element models. I really like the geometry module, and the fact that one can reuse entities that have been used for, say, a volume boolean operation. I have also got used to the meshing module now. Like with most really powerful software, once you get used to its special way of doing things it is plain sailing. Perhaps coming from a different software suite made things harder to learn rather than easier.

Anyway, the thing that has been bothering me for some time is scripting, or more specifically how to generate models on the fly by calling Salome from another program.

The situation

Consider the following example:

I am using a commercial optimization package to control my simulations. The program decides what input variables to use depending on it’s optimization algorithm and calls an external standalone script or executable. In this case I tell it to call a Python script and the script reads in the given variables. Next I have to generate a model, do a calculation and post-process to get the objective function all on-the-fly and controlled by Python.  The objective is then returned to the optimization program, which then decides which variables to use next. This process repeats until some convergence condition is met, or a maximum number of iterations has been reached.

Sub-optimal approach (IMHO)

In this example my controller script must generate (or modify) a model script file and call the modelling/meshing program in batch mode, while passing to it the model script.  Salome uses Python as its own internal scripting language. A python script can be called from inside the Salome GUI, or it can be called from the command line using the runAppli executable, found in the Salome program directory. In Python this can be done easily:
subprocess.call('%s/runAppli -t python modelscript.py' % SalomeExecutablePath, shell=True)
Unfortunately it is not possible to pass arguments to your script via runAppli arguments by listing them after the script file name. That would be one way to get the design variables to it, and they could then be found with sys.argv.
Another solution would be to use my controller script to generate or modify the model script. This seems convoluted to me (and not very Pythonic) so what I wanted to do was forego the runAppli route and import the modules that Salome uses directly into my controller script. Alas, no amount of Googling presented me with a way to do this.  When Salome dumps a script it includes a load of module import steps and I had hoped that, by giving my OS the library paths, I could import the same modules outside of Salome and make use of them. It appears that this is not the case. I don’t know what is going on behind the surface but I guess Salome uses the modules to control the executable but still needs the program itself to perform its work.

The solution

In the end a much simpler method seems to be the only option. The controller script writes the design variables to a text file and my Salome model script reads the variables in from this file. That way the model script itself does not need to be modified between runs. Simple, effective and totally obvious!

Schematic of the idea

Perhaps a better diagram would be a nested diagram, with the order of calls being represented by a parent/child relationship.

Nested schematic of the process showing the parent/child relationship between the programs making calls, and the programs (or scripts) being called.

We can dream

Still, I would like to know if I can import the Salome libraries into my controller script and use them to generate a FE mesh without having to call Salome the program at all. It is all based on Python anyway (this is probably not true, especially for 3rd party bits like the meshers), so why not (OK I guess I just answered that myself)?  Then I would be able to do everything in one Python script, instead of having a separate model script.