Tutorial for integrating the CoSimIO using the Python interface
Table of Contents
- What you need
- Building the CoSimIO
- Hello CosimIO
- Connecting and Disconnecting
- Data Exchange
- Mesh Exchange
- Next steps
This tutorial helps you to integrate the CoSimIO into a solver/software-tool using the Python interface.
What you need
- Downloading the CosimIO from the repository:
git clone https://github.com/KratosMultiphysics/CoSimIO.git -
A C++11 compatible compiler. This includes most of the major CPP compilers in Windows, Linux, and Mac. You may find a detailed list of C++11 compatible compilers here
- A developer version of Python. It is recommended to use Python >= v3.5
Building the CoSimIO
The Python interface is located in co_sim_io/python folder of the repository. It uses the pybind11 library for exposing the C++ code to Python. It is provided in the expternal_libraries/pybind11 folder of this repo.
One may use the build_python.sh or build_python.bat script from the CoSimIO root folder to create a library of the python interface:
- For GNU/Linux or MacOS:
$ bash scripts/build_python.sh -
For Windows OS:
$ scripts/build_python.batThis will compile the binaries and install them into the
bin/subfolder of CoSimIO, together with the CoSimIO Python module. Check here for the available build options.
The created folder structure should look like this:
| - bin
| - PyCoSimIO.cpython-35m-x86_64-linux-gnu.so # (Linux version)
- CoSimIO
| - __init__.py
Remember to add the /bin folder to your PYTHONPATH. For Linux this should look like the following:
export PYTHONPATH=$PYTHONPATH:/path/to/CoSimIO/bin
Usually pybind automatically detects the Python installation. Sometimes it can however be necessary to explicitly specify the target Python version. This can be achieved through CMake by setting PYBIND11_PYTHON_VERSION or an exact Python installation can be specified with PYTHON_EXECUTABLE. For example:
-DPYBIND11_PYTHON_VERSION=3.6
# or
-DPYTHON_EXECUTABLE=path/to/python_executable
see also the corresponding pybind documentation.
If Python cannot find the CoSimIO then check if the version of Python used for the compilation is the same as the version of Python used. E.g. when compiling CoSimIO with Python 3.6 it is not possible to import it when using Python 3.8. Here Python issues a ModuleNotFoundError.
This can easily be checked with the file extension of the compiled CoSimIO module.
Example: When using Python 3.5 the name of the compiled module will be sth like PyCoSimIO.cp35-win_amd64.pyd (Windows), PyCoSimIO.cpython-35m-x86_64-linux-gnu.so (Linux) or PyCoSimIO.cpython-35m-darwin.so (MacOS).
Hello CosimIO
After integrating the CoSimIO in your code now it’s time to say hello
import CoSimIO
info = CoSimIO.Hello()
Please note that this method like other methods in CoSimIO returns a CoSimIO::Info object. This object is a versatile container holding important information about the operation that has been done. See here for the documentation. In this case, it contains the version of the CoSimIO library which can be queried:
print(info)
The Info class also provides Get... methods for retrieving certain values knowing their type:
major_version = info.GetInt("major_version")
minor_version = info.GetInt("minor_version")
patch_version = info.GetString("patch_version")
This example can be found in integration_tutorials/python/hello.py.
Connecting and Disconnecting
The first step to establish a connection to Kratos CoSimulation is to use the Connect method:
# The connect should be called before any CosimIO method
info = CoSimIO.Connect(settings)
First of all, you may notice that Connect method takes a CoSimIO::Info as its argument. This container can be used to pass additional information about the solver/software-tool or connection settings to the CoSimIO:
settings = CoSimIO.Info()
settings.SetString("my_name", "py_connect_disconnect_a") # my name
settings.SetString("connect_to", "py_connect_disconnect_b") # to whom I want to connect to
settings.SetInt("echo_level", 1)
settings.SetString("version", "1.25")
It is very important that the settings for my_name and connect_to are set correctly, otherwise the connection cannot be established!
E.g in the above example one code sets my_name as py_connect_disconnect_a and connect_to as py_connect_disconnect_b. This means that the other code has to use the same settings but reversed: my_name must be py_connect_disconnect_b and connect_to must be py_connect_disconnect_a.
This method returns a Info object containing information about the connection which can be queried using GetString method. For further calls to CoSimIO it is necessary to get the connection_name:
connection_name = info.GetString("connection_name")
Similar things work for the Disconnect method.
Now putting together everything:
import CoSimIO
settings = CoSimIO.Info()
settings.SetString("my_name", "py_connect_disconnect_a") # my name
settings.SetString("connect_to", "py_connect_disconnect_b") # to whom I want to connect to
settings.SetInt("echo_level", 1)
settings.SetString("solver_version", "1.25")
info = CoSimIO.Connect(settings)
# The connect_info contains now:
# - The name of the connection ("connection_name") to be used for further calls to CoSimIO
# - The status of the connection ("connection_status")
connection_name = info.GetString("connection_name") # getting name of connection for future calls
if info.GetInt("connection_status") == CoSimIO.ConnectionStatus.Connected:
print("Connected!")
disconnect_settings = CoSimIO.Info()
disconnect_settings.SetString("connection_name", connection_name)
info = CoSimIO.Disconnect(disconnect_settings)
if info.GetInt("connection_status") == CoSimIO.ConnectionStatus.Disconnected:
print("Disconnected!")
This example can be found in integration_tutorials/python/connect_disconnect_a.py and integration_tutorials/python/connect_disconnect_b.py.
Data Exchange
Make sure to connect (refer Connecting and Disconnecting) before Data Exchange.
One of the important missions of the CoSimIO is to send and recieve data between different solvers/software tools. The ExportData method can be used to send data to the Kratos or directly to another solver/software-tool:
info = CoSimIO.Info()
info.SetString("identifier", "vector_of_pi")
info.SetString("connection_name", connection_name) # connection_name is obtained from calling "Connect"
data_to_be_export = CoSimIO.DoubleVector([3.14,3.14,3.14,3.14]) # generic Vector to avoid memory copy when going from python to C++ and back
return_info = CoSimIO.ExportData(info, data_to_be_export)
The ImportData should be used on the other side to recieve data:
info = CoSimIO.Info()
info.SetString("identifier", "vector_of_pi")
info.SetString("connection_name", connection_name)
data_to_be_import = CoSimIO.DoubleVector()
return_info = CoSimIO.ImportData(info, data_to_be_import)
It is important to mention that ImportData will clear and resize the vector if needed.
This example can be found in integration_tutorials/python/export_data.py and integration_tutorials/python/import_data.py.
Mesh Exchange
Make sure to connect (refer Connecting and Disconnecting) before Mesh Exchange.
After seeing how we transfer raw data between solvers/software-tools, it is time to see how we can export and import meshes. For exporting the mesh one may use the ExportMesh method:
info = CoSimIO.Info()
info.SetString("identifier", "fluid_mesh")
info.SetString("connection_name", connection_name) # connection_name is obtained from calling "Connect"
model_part = CoSimIO.ModelPart("name_of_model_part_to_export")
export_info = CoSimIO.ExportMesh(info, model_part)
The argument model_part is of type CoSimIO::ModelPart and contains a mesh. Its usage is explained here.
On the other side one can use the ImportMesh() method to get the mesh sent by the export:
info = CoSimIO.Info()
info.SetString("identifier", "fluid_mesh")
info.SetString("connection_name", "test_connection")
model_part = CoSimIO.ModelPart("name_of_imported_model_part")
import_info = CoSimIO.ImportMesh(info, model_part)
This example can be found in integration_tutorials/python/export_mesh.py and integration_tutorials/python/import_mesh.py.
Next steps
In the next tutorial, a connection to Kratos is established and basic data exchange with Kratos is done.