Repository: FloatingArrayDesign/MoorDyn (language: python)

Issue:
Could not install in endeavouros
Hello! I was trying to install MoorDyn (v2 branch) on an endeavouros system (see details below) running on a Vostro 5320 (Dell Inc.). However, the installation did not worked (make threw an error, related to the python library). The output suggested that I need to install python packages with 

`pacman -S python-package`

instead of with pip. Also, it gave the alternative of adding 

`--break-system-packages`

at the end of the pip command. Thus I need to add it to /wrappers/python/CMakeLists.txt:49

Then it worked. Maybe this is worth considering. Thanks a lot for the work. 


The output of uname -a is:
`6.4.4-arch1-1 #1 SMP PREEMPT_DYNAMIC Wed, 19 Jul 2023 19:19:38 +0000 x86_64 GNU/Linux`

Linux pypi packages do not work
See #122 

The problem is that vtk is built on a too recent Ubuntu distro. I think I should move the cibuildwheels to manylinux_2014, and change the vtk-buikds to use that very same container
Fixes initialization location of fixed bodies
Resolves an issue where fixed bodies only initialized at 0,0,0,0,0,0 irregardless of what was specified in the input file. This was due to fixed bodies not initializing, and so default values were used. 


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/python-wheels-manylinux-arch.yml b/.github/workflows/python-wheels-manylinux-arch.yml
new file mode 100644
index 00000000..47a12862
--- /dev/null
+++ b/.github/workflows/python-wheels-manylinux-arch.yml
@@ -0,0 +1,74 @@
+name: Python-manylinux-arch
+
+on:
+  workflow_call:
+    inputs:
+      arch:
+        description: 'Architecture target'
+        required: true
+        type: string
+        
+permissions: write-all
+
+env:
+  # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
+  BUILD_TYPE: Release
+  VTK_VERSION_MAJOR: 9
+  VTK_VERSION_MINOR: 2
+  VTK_VERSION_PATCH: 6
+
+jobs:
+  build_wheels:
+    name: Build Python wheels
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-22.04]
+
+    steps:
+      - uses: actions/checkout@v4
+
+      # Used to host cibuildwheel
+      - uses: actions/setup-python@v4
+        with:
+          python-version: '3.x' 
+
+      - name: Create setup.py
+        run: |
+            mv wrappers/python/wheels.github/* ./
+            python set_version.py
+            python set_eigen_data.py
+            rm set_version.py set_eigen_data.py            
+        shell: bash
+
+      - name: download pre-built VTK static library
+        uses: suisei-cn/actions-download-file@v1.4.0
+        with:
+          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-manylinux2014_${{inputs.arch}}.tar.gz
+          target: ${{github.workspace}}/
+
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: all
+
+      - name: Build wheels
+        uses: pypa/cibuildwheel@v2.16.2
+        with:
+            output-dir: dist
+        env:
+          # configure cibuildwheel to build native archs ('auto'), and some
+          # emulated ones
+          CIBW_ARCHS_LINUX: ${{inputs.arch}}
+          # Skip 32-bit wheels builds as well as musllinux
+          CIBW_SKIP: "*-win32 *musllinux*"
+          CIBW_BEFORE_ALL_LINUX: >
+            echo "Considering vtk-manylinux2014_`uname -m`.tar.gz..." &&
+            mkdir -p vtk &&
+            tar -xvzf vtk-manylinux2014_`uname -m`.tar.gz -C vtk/
+
+      - uses: actions/upload-artifact@v3
+        id: build_wheels
+        with:
+          name: python-wheels-${{inputs.arch}}
+          path: ./dist/*
diff --git a/.github/workflows/python-wheels.yml b/.github/workflows/python-wheels.yml
index b7fe66a2..6fae87b4 100644
--- a/.github/workflows/python-wheels.yml
+++ b/.github/workflows/python-wheels.yml
@@ -11,22 +11,15 @@ env:
   BUILD_TYPE: Release
   VTK_VERSION_MAJOR: 9
   VTK_VERSION_MINOR: 2
-  VTK_VERSION_PATCH: 5
+  VTK_VERSION_PATCH: 6
 
 jobs:
   build_wheels:
-    name: Build Python wheels
+    name: Build Python wheels x86_64
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
         os: [ubuntu-22.04, windows-latest, macOS-latest]
-    env:
-      # Skip 32-bit wheels builds
-      CIBW_SKIP: "*-win32 *_i686"
-      CIBW_BEFORE_ALL_LINUX: >
-        echo "Considering vtk-Linux-`uname -m`.tar.gz..." &&
-        mkdir -p vtk &&
-        tar -xvzf vtk-Linux-`uname -m`.tar.gz -C vtk/
 
     steps:
       - uses: actions/checkout@v4
@@ -41,13 +34,9 @@ jobs:
             mv wrappers/python/wheels.github/* ./
             python set_version.py
             python set_eigen_data.py
-            rm set_version.py set_eigen_data.py
-            
+            rm set_version.py set_eigen_data.py            
         shell: bash
 
-      - name: Install cibuildwheel
-        run: python -m pip install cibuildwheel
-
       - name: download pre-built VTK static library (non-Linux)
         uses: suisei-cn/actions-download-file@v1.4.0
         with:
@@ -58,35 +47,14 @@ jobs:
       - name: download pre-built VTK static library (Linux-x86_64)
         uses: suisei-cn/actions-download-file@v1.4.0
         with:
-          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-x86_64.tar.gz
-          target: ${{github.workspace}}/
-        if: runner.os == 'Linux'
-
-      - name: download pre-built VTK static library (Linux-aarch64)
-        uses: suisei-cn/actions-download-file@v1.4.0
-        with:
-          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-aarch64.tar.gz
-          target: ${{github.workspace}}/
-        if: runner.os == 'Linux'
-
-      - name: download pre-built VTK static library (Linux-armv7)
-        uses: suisei-cn/actions-download-file@v1.4.0
-        with:
-          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-armv7.tar.gz
+          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-manylinux2014_x86_64.tar.gz
           target: ${{github.workspace}}/
         if: runner.os == 'Linux'
 
-      - name: download pre-built VTK static library (Linux-ppc64le)
+      - name: download pre-built VTK static library (Linux-i686)
         uses: suisei-cn/actions-download-file@v1.4.0
         with:
-          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-ppc64le.tar.gz
-          target: ${{github.workspace}}/
-        if: runner.os == 'Linux'
-
-      - name: download pre-built VTK static library (Linux-s390x)
-        uses: suisei-cn/actions-download-file@v1.4.0
-        with:
-          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-s390x.tar.gz
+          url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-manylinux2014_i686.tar.gz
           target: ${{github.workspace}}/
         if: runner.os == 'Linux'
 
@@ -104,18 +72,57 @@ jobs:
         run: python setup.py sdist
         if: runner.os == 'Linux'
 
+      - name: Set up QEMU
+        uses: docker/setup-qemu-action@v3
+        with:
+          platforms: all
+        if: runner.os == 'Linux'
+
       - name: Build wheels
-        run: python -m cibuildwheel --output-dir dist
+        uses: pypa/cibuildwheel@v2.16.2
+        with:
+            output-dir: dist
+        env:
+          # configure cibuildwheel to build native archs ('auto'), and some
+          # emulated ones
+          CIBW_ARCHS_LINUX: auto
+          # Skip 32-bit wheels builds as well as musllinux
+          CIBW_SKIP: "*-win32 *musllinux*"
+          CIBW_BEFORE_ALL_LINUX: >
+            echo "Considering vtk-manylinux2014_`uname -m`.tar.gz..." &&
+            mkdir -p vtk &&
+            tar -xvzf vtk-manylinux2014_`uname -m`.tar.gz -C vtk/
 
       - uses: actions/upload-artifact@v3
         id: build_wheels
         with:
-          name: python-package-distributions
+          name: python-wheels-x86_64
           path: ./dist/*
 
+  build_aarch64:
+    name: Build Python wheels aarch64
+    uses: FloatingArrayDesign/MoorDyn/.github/workflows/python-wheels-manylinux-arch.yml@master
+    with:
+      arch: "aarch64"
+    secrets: inherit
+
+  build_ppc64le:
+    name: Build Python wheels ppc64le
+    uses: FloatingArrayDesign/MoorDyn/.github/workflows/python-wheels-manylinux-arch.yml@master
+    with:
+      arch: "ppc64le"
+    secrets: inherit
+    
+  build_s390x:
+    name: Build Python wheels s390x
+    uses: FloatingArrayDesign/MoorDyn/.github/workflows/python-wheels-manylinux-arch.yml@master
+    with:
+      arch: "s390x"
+    secrets: inherit
+
   publish:
     runs-on: ${{ matrix.os }}
-    needs: [build_wheels]
+    needs: [build_wheels, build_aarch64, build_ppc64le, build_s390x]
     strategy:
         matrix:
             os: [ubuntu-22.04]
@@ -123,17 +130,35 @@ jobs:
     steps:
       - uses: actions/checkout@v4
 
-      - name: Download all the dists
+      - name: Download x86_64 dists
         uses: actions/download-artifact@v3
         with:
-          name: python-package-distributions
+          name: python-wheels-x86_64
           path: dist/
-        
+
+      - name: Download aarch64 dists
+        uses: actions/download-artifact@v3
+        with:
+          name: python-wheels-aarch64
+          path: dist/
+
+      - name: Download ppc64le dists
+        uses: actions/download-artifact@v3
+        with:
+          name: python-wheels-ppc64le
+          path: dist/
+
+      - name: Download s390x dists
+        uses: actions/download-artifact@v3
+        with:
+          name: python-wheels-s390x
+          path: dist/
+
       - name: Publish package to TestPyPI
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
-          # password: ${{ secrets.MOORDYN_TESTPYPI_API }}
-          # repository-url: https://test.pypi.org/legacy/
-          password: ${{ secrets.MOORDYN_PYPI_API }}
-          repository-url: https://upload.pypi.org/legacy/
+          password: ${{ secrets.MOORDYN_TESTPYPI_API }}
+          repository-url: https://test.pypi.org/legacy/
+          # password: ${{ secrets.MOORDYN_PYPI_API }}
+          # repository-url: https://upload.pypi.org/legacy/
           skip-existing: true
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3e815cf0..617f55ef 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,7 +1,7 @@
 cmake_minimum_required(VERSION 3.10)
 set(MOORDYN_MAJOR_VERSION 2)
 set(MOORDYN_MINOR_VERSION 2)
-set(MOORDYN_PATCH_VERSION 1)
+set(MOORDYN_PATCH_VERSION 2)
 set(MOORDYN_VERSION ${MOORDYN_MAJOR_VERSION}.${MOORDYN_MINOR_VERSION})
 project(Moordyn VERSION ${MOORDYN_VERSION})
 
@@ -25,6 +25,8 @@ set(EXTERNAL_EIGEN OFF CACHE BOOL
     "Use the Eigen3 installed in the system")
 set(USE_VTK OFF CACHE BOOL
     "Link with VTK to produce output binary files")
+set(MOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY OFF CACHE BOOL
+    "Specifically tells MoorDyn to ignore the VTK dependency on the exported package. This can be useful if VTK was linked statically")
 set(FORTRAN_WRAPPER OFF CACHE BOOL
     "Build the Fortran module")
 set(MATLAB_WRAPPER OFF CACHE BOOL
@@ -40,11 +42,23 @@ set(MOORDYN_SINGLEPRECISSION OFF CACHE BOOL
 set(MOORDYN_SSE "OFF" CACHE STRING "Use enhanced instructions set")
 set_property(CACHE MOORDYN_SSE PROPERTY STRINGS OFF SSE SSE2 SSE4 AVX AVX2 AVX512)
 set(MOORDYN_FASTMATH OFF CACHE BOOL "Enhances performance at the cost of accuracy")
+
+mark_as_advanced(MOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY)
 mark_as_advanced(PYTHON_WRAPPER_USERINSTALL)
 mark_as_advanced(MOORDYN_SINGLEPRECISSION)
 mark_as_advanced(MOORDYN_SSE)
 mark_as_advanced(MOORDYN_FASTMATH)
 
+# Set RelWithDebInfo as the default build type
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+  message(STATUS "Setting build type to 'RelWithDebInfo' as none was specified.")
+  set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE
+      STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel" FORCE)
+  # Set the possible values of build type for cmake-gui
+  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
+    "None" "Debug" "Release" "RelWithDebInfo" "MinSizeRel")
+endif()
+
 # Look for the dependencies
 if(${USE_VTK})
     find_package(VTK
@@ -147,6 +161,14 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
 endif()
 if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) AND BUILD_TESTING)
     add_subdirectory(extern/Catch2)
+    get_cmake_property(_variableNames VARIABLES)
+    list (SORT _variableNames)
+    foreach (_variableName ${_variableNames})
+        string(FIND "${_variableName}" "CATCH_CONFIG" out)
+        if("${out}" EQUAL 0)
+            mark_as_advanced(${_variableName})
+        endif()
+    endforeach()
     add_subdirectory(tests)
 endif()
 
diff --git a/cmake/MoorDynConfig.cmake b/cmake/MoorDynConfig.cmake
index adda8dab..08a7cad3 100644
--- a/cmake/MoorDynConfig.cmake
+++ b/cmake/MoorDynConfig.cmake
@@ -2,6 +2,7 @@ include(CMakeFindDependencyMacro)
 
 set(MOORDYN_EXTERNAL_EIGEN @EXTERNAL_EIGEN@)
 set(MOORDYN_USE_VTK @USE_VTK@)
+set(MOORDYN_SKIP_VTK_DEP @MOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY@)
 set(MOORDYN_PYTHON_WRAPPER @PYTHON_WRAPPER@)
 set(MOORDYN_FORTRAN_WRAPPER @FORTRAN_WRAPPER@)
 set(MOORDYN_MATLAB_WRAPPER @MATLAB_WRAPPER@)
@@ -12,7 +13,7 @@ set(MOORDYN_FASTMATH @MOORDYN_FASTMATH@)
 if(MOORDYN_EXTERNAL_EIGEN)
     find_dependency(Eigen3)
 endif()
-if(MOORDYN_USE_VTK)
+if(MOORDYN_USE_VTK AND NOT MOORDYN_SKIP_VTK_DEP)
     find_dependency(VTK)
 endif()
 
diff --git a/docs/drivers.rst b/docs/drivers.rst
index 4b9667a4..c8bcdefd 100644
--- a/docs/drivers.rst
+++ b/docs/drivers.rst
@@ -157,8 +157,9 @@ library. Below is an example of this on MacOS with MoorDyn compiled as a
    vector_size = 6 # 6DOF coupled object
    size = (len(time), vector_size)
 
-   x = np.zeros(size)
-   xd = np.zeros(size)
+   #specifying correct dtypes for conversion to C types
+   x = np.zeros(size, dtype = float)
+   xd = np.zeros(size, dtype = float)
 
    dylib_path = 'MoorDyn/compile/DYLIB/libmoordyn2.dylib'
    filename = path+rootname+extension
diff --git a/source/Body.cpp b/source/Body.cpp
index c68eaa54..bcf52fb6 100644
--- a/source/Body.cpp
+++ b/source/Body.cpp
@@ -77,7 +77,15 @@ Body::setup(int number_in,
 		bodyI = I_in;
 		bodyCdA = CdA_in;
 		bodyCa = Ca_in;
-	} else // other types of bodies have no need for these variables...
+	} else if (type == FIXED){ // fixed bodies have no need for these variables other than position...
+		bodyM = 0.0;
+		bodyV = 0.0;
+		body_r6.head<3>() = r6_in.head<3>();
+		body_r6.tail<3>() = deg2rad * r6_in.tail<3>();
+		bodyI = vec::Zero();
+		bodyCdA = vec6::Zero();
+		bodyCa = vec6::Zero();
+    } else // coupled bodies have no need for these variables...
 	{
 		bodyM = 0.0;
 		bodyV = 0.0;
@@ -305,7 +313,7 @@ real
 Body::GetBodyOutput(OutChanProps outChan)
 {
 
-	vec3 rotations = Quat2Euler(r7.quat);
+	vec3 rotations = rad2deg * Quat2Euler(r7.quat);
 
 	if (outChan.QType == PosX)
 		return r7.pos.x();
@@ -375,9 +383,10 @@ Body::initiateStep(vec6 r, vec6 rd)
 		rd_ves = rd;
 		return;
 	}
-	if (type == FIXED) // if the ground body, set the BCs to stationary
+	if (type == FIXED) // if fixed body, set the BCs to stationary
 	{
-		r_ves = vec6::Zero();
+		if (bodyId == 0) r_ves = vec6::Zero(); // special ground body case
+		else r_ves = r;
 		rd_ves = vec6::Zero();
 		return;
 	}
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 3985b3ad..94d675f8 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -51,12 +51,25 @@ set(MOORDYN_HEADERS
 )
 
 set(MOORDYN_PUBLIC_DEPS "")
+set(MOORDYN_PRIVATE_DEPS "")
 if(USE_VTK)
-    list(APPEND MOORDYN_PUBLIC_DEPS VTK::CommonCore
-                                    VTK::IOCore
-                                    VTK::IOXML
-                                    VTK::IOGeometry
-                                    VTK::FiltersGeneral)
+    if(MOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY)
+        list(APPEND MOORDYN_PRIVATE_DEPS VTK::CommonCore
+                                         VTK::IOCore
+                                         VTK::IOXML
+                                         VTK::IOGeometry
+                                         VTK::FiltersGeneral)
+        get_target_property(MOORDYN_PRIVATE_INCLUDE_DIRS
+                            VTK::CommonCore
+                            INTERFACE_INCLUDE_DIRECTORIES)
+    else()
+        list(APPEND MOORDYN_PUBLIC_DEPS VTK::CommonCore
+                                        VTK::IOCore
+                                        VTK::IOXML
+                                        VTK::IOGeometry
+                                        VTK::FiltersGeneral)
+        set(MOORDYN_PRIVATE_INCLUDE_DIRS "")
+    endif()
     list(APPEND MOORDYN_HEADERS Util/VTK_Util.hpp)
     list(APPEND MOORDYN_SRCS Util/VTK_Util.cpp)
 endif()
@@ -86,7 +99,9 @@ if(${CMAKE_VERSION} VERSION_GREATER "3.15")
   endif()
 endif()
 target_compile_definitions(moordyn PUBLIC MoorDyn_EXPORTS)
-target_link_libraries(moordyn PUBLIC ${MOORDYN_PUBLIC_DEPS})
+target_link_libraries(moordyn PUBLIC ${MOORDYN_PUBLIC_DEPS}
+                              PRIVATE ${MOORDYN_PRIVATE_DEPS})
+target_include_directories(moordyn PRIVATE ${MOORDYN_PRIVATE_INCLUDE_DIRS})
 
 install(TARGETS moordyn EXPORT MoorDynTargets
   LIBRARY DESTINATION lib
diff --git a/source/MoorDyn2.cpp b/source/MoorDyn2.cpp
index e25145e9..682a4f14 100644
--- a/source/MoorDyn2.cpp
+++ b/source/MoorDyn2.cpp
@@ -205,6 +205,11 @@ moordyn::MoorDyn::Init(const double* x, const double* xd, bool skip_ic)
 	// call ground body to update all the fixed things...
 	GroundBody->initializeUnfreeBody();
 
+	// intialize fixed bodies and attached objects
+	for (auto l : FixedBodyIs){
+		BodyList[l]->initializeUnfreeBody(BodyList[l]->body_r6, vec6::Zero());
+	}
+
 	// initialize coupled objects based on passed kinematics
 	int ix = 0;
 
@@ -1732,6 +1737,7 @@ moordyn::MoorDyn::readBody(string inputText)
 		// it is fixed  (this would just be used if someone wanted
 		// to temporarly fix a body that things were attached to)
 		type = Body::FIXED;
+		FixedBodyIs.push_back(ui_size(BodyList));
 	} else if (str::isOneOf(let1, { "VESSEL", "VES", "COUPLED", "CPLD" })) {
 		// it is coupled - controlled from outside
 		type = Body::COUPLED;
diff --git a/source/MoorDyn2.hpp b/source/MoorDyn2.hpp
index 1f45c246..55290e44 100644
--- a/source/MoorDyn2.hpp
+++ b/source/MoorDyn2.hpp
@@ -475,6 +475,8 @@ class MoorDyn final : public io::IO
 
 	/// vector of free body indices in BodyList vector
 	vector<unsigned int> FreeBodyIs;
+	/// vector of fixed body indices in BodyList vector
+	vector<unsigned int> FixedBodyIs;
 	/// vector of coupled/fairlead body indices in BodyList vector
 	vector<unsigned int> CpldBodyIs;
 
diff --git a/wrappers/python/CMakeLists.txt b/wrappers/python/CMakeLists.txt
index 90a72878..e42a9589 100644
--- a/wrappers/python/CMakeLists.txt
+++ b/wrappers/python/CMakeLists.txt
@@ -42,8 +42,14 @@ add_custom_target(python_wrapper ALL DEPENDS ${OUTPUT})
 add_dependencies(python_wrapper moordyn)
 
 # Prepare the installation if eventually required
+set(PY_INSTALL_ARGS "")
 if(${PYTHON_WRAPPER_USERINSTALL})
-    set(PY_INSTALL_ARGS "--user")
+    set(PY_INSTALL_ARGS "${PY_INSTALL_ARGS} --user")
+endif()
+if (UNIX)
+    if((${Python_VERSION_MAJOR} GREATER 3) OR ((${Python_VERSION_MAJOR} EQUAL 3) AND (${Python_VERSION_MINOR} GREATER 10)))
+        set(PY_INSTALL_ARGS "${PY_INSTALL_ARGS} --break-system-packages")
+    endif()
 endif()
 install(CODE "
   execute_process(COMMAND ${Python_EXECUTABLE} -m pip install dist/moordyn-${MOORDYN_VERSION}.tar.gz ${PY_INSTALL_ARGS}


Test patch:
diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml
index 36daddf5..c352129b 100644
--- a/.github/workflows/build-test.yml
+++ b/.github/workflows/build-test.yml
@@ -14,7 +14,7 @@ env:
   BUILD_TYPE: Release
   VTK_VERSION_MAJOR: 9
   VTK_VERSION_MINOR: 2
-  VTK_VERSION_PATCH: 5
+  VTK_VERSION_PATCH: 6
 
 jobs:
   create_release:
@@ -92,33 +92,50 @@ jobs:
         compiler: gcc
       if: runner.os == 'Linux'
 
+    - name: Install VTK (Linux)
+      run: |
+        sudo apt-get -qq update
+        sudo apt-get -qq -y install libvtk9-dev
+      if: runner.os == 'Linux'
+
+    - name: Install VTK (MacOS)
+      run: |
+        brew install vtk
+      if: runner.os == 'MacOS'
+
     - name: download pre-built VTK static library
       uses: suisei-cn/actions-download-file@v1.4.0
       with:
         url: https://github.com/sanguinariojoe/vtk-builds/releases/download/VTK-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}.${{env.VTK_VERSION_PATCH}}-static/vtk-${{runner.os}}-x86_64.tar.gz
         target: ${{github.workspace}}/
+      if: runner.os == 'Windows'
 
-    - name: Create folders
+    - name: Create VTK folder
       run: |
           mkdir -p ${{github.workspace}}/vtk
-          mkdir -p ${{github.workspace}}/install
+      if: runner.os == 'Windows'
 
     - name: Extract VTK tgz
       run: |
           tar -xvzf vtk-${{runner.os}}-x86_64.tar.gz -C vtk/
+      if: runner.os == 'Windows'
+
+    - name: Create install folder
+      run: |
+          mkdir -p ${{github.workspace}}/install
 
     - name: Configure CMake (Linux)
-      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=ON -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DVTK_DIR=${{github.workspace}}/vtk/lib/cmake/vtk-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}/ -DBUILD_TESTING=ON
+      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=ON -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DBUILD_TESTING=ON
       if: runner.os == 'Linux'
 
+    - name: Configure CMake (MacOS)
+      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=OFF -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DBUILD_TESTING=ON
+      if: runner.os == 'MacOS'
+
     - name: Configure CMake (Windows)
-      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=OFF -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DVTK_DIR=${{github.workspace}}/vtk/lib/cmake/vtk-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}/ -DBUILD_TESTING=ON
+      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=OFF -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DVTK_DIR=${{github.workspace}}/vtk/lib/cmake/vtk-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}/ -DMOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY=ON -DBUILD_TESTING=ON
       if: runner.os == 'Windows'
 
-    - name: Configure CMake (Mac)
-      run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_INSTALL_PREFIX=${{github.workspace}}/install -DCMAKE_VERBOSE_MAKEFILE:BOOL=ON -DEXTERNAL_EIGEN:BOOL=OFF -DPYTHON_WRAPPER:BOOL=OFF -DFORTRAN_WRAPPER:BOOL=OFF -DRUST_WRAPPER:BOOL=OFF -DUSE_VTK=ON -DVTK_DIR=${{github.workspace}}/vtk/lib/cmake/vtk-${{env.VTK_VERSION_MAJOR}}.${{env.VTK_VERSION_MINOR}}/ -DBUILD_TESTING=ON
-      if: runner.os == 'macOS'
-
     - name: Build
       id: build
       run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
@@ -139,11 +156,6 @@ jobs:
       # We are just testing in Linux
       run: ctest -C ${{env.BUILD_TYPE}}
 
-    - name: Install
-      working-directory: ${{github.workspace}}/build
-      # We are just testing in Linux
-      run: cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
-
     - name: Create Installer
       working-directory: ${{github.workspace}}/build
       shell: bash
@@ -162,26 +174,26 @@ jobs:
         asset_content_type: application/exe
       if: ${{ (github.event_name == 'push') && (runner.os == 'Linux') }}
 
-    - name: Upload Windows installer
-      id: upload-windows-installer
+    - name: Upload MacOS installer
+      id: upload-macos-installer
       uses: actions/upload-release-asset@v1
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
       with:
         upload_url: ${{ needs.create_release.outputs.upload_url }}
-        asset_path: ${{github.workspace}}/build/Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-win64.exe
-        asset_name: Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-win64.exe
+        asset_path: ${{github.workspace}}/build/Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-Darwin.sh
+        asset_name: Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-Darwin.sh
         asset_content_type: application/exe
-      if: ${{ (github.event_name == 'push') && (runner.os == 'Windows') }}
+      if: ${{ (github.event_name == 'push') && (runner.os == 'MacOS') }}
 
-    - name: Upload MacOS installer
-      id: upload-macos-installer
+    - name: Upload Windows installer
+      id: upload-windows-installer
       uses: actions/upload-release-asset@v1
       env:
         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
       with:
         upload_url: ${{ needs.create_release.outputs.upload_url }}
-        asset_path: ${{github.workspace}}/build/Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-Darwin.sh
-        asset_name: Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-Darwin.sh
+        asset_path: ${{github.workspace}}/build/Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-win64.exe
+        asset_name: Moordyn-${{steps.moordyn_version.outputs.moordyn_version}}-win64.exe
         asset_content_type: application/exe
-      if: ${{ (github.event_name == 'push') && (runner.os == 'MacOS') }}
+      if: ${{ (github.event_name == 'push') && (runner.os == 'Windows') }}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 57408555..8257f9bd 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -42,8 +42,21 @@ set(CATCH2_TESTS
 )
 
 function(make_executable test_name)
+    set(TEST_PRIVATE_DEPS "moordyn;")
     add_executable(${test_name} ${test_name}.cpp)
-    target_link_libraries(${test_name} PRIVATE moordyn)
+    if(USE_VTK AND MOORDYN_PACKAGE_IGNORE_VTK_DEPENDENCY)
+        list(APPEND TEST_PRIVATE_DEPS VTK::CommonCore
+                                         VTK::IOCore
+                                         VTK::IOXML
+                                         VTK::IOGeometry
+                                         VTK::FiltersGeneral)
+        get_target_property(TEST_PRIVATE_INCLUDE_DIRS
+                            VTK::CommonCore
+                            INTERFACE_INCLUDE_DIRECTORIES)
+        target_include_directories(${test_name}
+                                   PRIVATE ${TEST_PRIVATE_INCLUDE_DIRS})
+    endif()
+    target_link_libraries(${test_name} PRIVATE ${TEST_PRIVATE_DEPS})
     add_dependencies(${test_name} Test_MooringConfigFiles)
 endfunction()