I have a Modern Fortran code with a nice python interface based on cython and iso-c-binding. It works except when I create in a script containing several python instances of my Fortran code. The computation behaves as if there is only one Fortran code running.
I enter a specific configuration for each python instance. But behind it is the same Fortran code (some variables are global inside the Fortran code).
A « non elegant » solution could be to duplicate the dynamic library and python interface of the Fortran code.
And my question is : can I isolate the two Fortran computations inside the python script ?
Is the issue that your Fortran code uses global module variables to store state, and you create two “instances” from Python, and the Python constructor initializes the global state in the first instance and overrides it with the second instance?
If so, the solution is to refactor your Fortran code to not have a global state, but rather store the state in a derived type, and pass this derived type to all functions that need the global variables. Then create some functions to create/destroy this derived type and each Python instance then creates its own derived type.
Alternatively you can run and communicate with your Fortran code as two different processes, but you can’t then wrap it using Cython/shared library, you would have to communicate with it using stdin/stdout, sort of like the chess GUI communicates with the chess engine (Protocols - Chessprogramming wiki).
Third option is to ensure there is always only one Python instance at a time, never running your code in parallel, so then it doesn’t matter that it has global state.
I am not sure it is possible to have the same program loaded as two different instances as a shared library.
I recommend the first option if you can do it, as it is always cleaner not to have any global state. If you have a huge code with lots of global state and thousands of functions to refactor, then you might need to go the second route, and implement a communication interface using stdin/stdout, and then interact with it via Python that way; or go the third route and enforce serial execution.