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.bat
This 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.