From 7f6de7fe30a8acfd16446c2033628855c88d65b7 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 17 Jul 2024 16:39:38 +0200 Subject: [PATCH 01/29] [py] Install python bindings into venv in build dir. --- Applications/Python/CMakeLists.txt | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index 06e3d7a9283..8ceba35d773 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -1,11 +1,31 @@ +set(_py_site_packages_dir + "lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages" +) +if(WIN32) + set(_py_site_packages_dir "Lib/site-packages") +endif() + # wheel: Install into Python module root dir (enables 'import ogs.simulator') set(_py_install_location ogs) if(NOT OGS_BUILD_WHEEL) - set(_py_install_location - "${CMAKE_INSTALL_LIBDIR}/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages/ogs" - ) + set(_py_install_location "{_py_site_packages_dir}/ogs") endif() + add_subdirectory(ogs) add_subdirectory(ogs.simulator) add_subdirectory(ogs.mesh) add_subdirectory(ogs.callbacks) + +if(OGS_USE_PIP) + set_target_properties( + simulator mesh callbacks + PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${LOCAL_VIRTUALENV_DIR}/${_py_site_packages_dir}/ogs + ) + file( + COPY ogs/. + DESTINATION ${LOCAL_VIRTUALENV_DIR}/${_py_site_packages_dir}/ogs + PATTERN "__pycache__" EXCLUDE + PATTERN "CMakeLists.txt" EXCLUDE + ) +endif() From 4b0db3b43fe0bc675bf6203d685d9bf24f312b99 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 17 Jul 2024 16:40:19 +0200 Subject: [PATCH 02/29] [cmake] When OGS_USE_PIP=ON cli wrapper uses build dir binaries. Requires direnv tool. --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 67d8a387b28..ebebc5510b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -237,6 +237,7 @@ endif() set(_envrc_content "[ -d \"${PROJECT_BINARY_DIR}/.venv\" ] && source ${PROJECT_BINARY_DIR}/.venv/bin/activate" "export PATH=$PATH:${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + "export OGS_USE_PATH=1" ) if(TFEL_WITH_PYTHON) set(_envrc_content "${_envrc_content}" From 59e925b6016fd55f3ac08ccfdc7ec4c2a2c9c425 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 17 Jul 2024 17:13:46 +0200 Subject: [PATCH 03/29] [T,py] Add pytest ctest. - pytest is added to requirements-dev.txt - 'pytest' ctest is added [T] Disable pytest on sanitizer build. --- Applications/Python/CMakeLists.txt | 18 ++++++++++++++++++ Tests/Data/requirements-dev.txt | 1 + pyproject.toml | 2 +- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index 8ceba35d773..18164c746f2 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -28,4 +28,22 @@ if(OGS_USE_PIP) PATTERN "__pycache__" EXCLUDE PATTERN "CMakeLists.txt" EXCLUDE ) + # Fails with libGitInfoLib.so: undefined symbol: __asan_report_load8 + if(NOT ENABLE_ASAN) + add_test( + NAME pytest + # TODO: currently failing with: + # + # Can't add new modules after the interpreter has been initialized + COMMAND pytest -c ${PROJECT_SOURCE_DIR}/pyproject.toml + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + ) + set_tests_properties(pytest PROPERTIES LABELS "default") + + add_dependencies( + ctest GMSH2OGS Layers2Grid AddFaultToVoxelGrid ExtractBoundary + vtkdiff + ) + endif() + endif() diff --git a/Tests/Data/requirements-dev.txt b/Tests/Data/requirements-dev.txt index 8362ab3cc62..a4011596b5e 100644 --- a/Tests/Data/requirements-dev.txt +++ b/Tests/Data/requirements-dev.txt @@ -3,3 +3,4 @@ nbformat==5.7.3 toml==0.10.2 jupytext==1.14.5 papermill==2.6.0 +pytest==8.2.2 diff --git a/pyproject.toml b/pyproject.toml index bff0fbe0fe6..8f0af55e70c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ local_scheme = "no-local-version" [tool.pytest.ini_options] testpaths = ["Tests"] -norecursedirs = ["Tests/Data"] +python_files = ["test_*.py"] [tool.cibuildwheel] archs = "auto64" From ce267122a0440c982839eda0d9b03b27bf640505 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 25 Jul 2024 15:50:25 +0200 Subject: [PATCH 04/29] [web] Added some instructions on pytest usage. --- .../devguide/advanced/python-wheel/index.md | 33 ++++++++++++++++--- .../devguide/packages/python-env/index.md | 2 +- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/web/content/docs/devguide/advanced/python-wheel/index.md b/web/content/docs/devguide/advanced/python-wheel/index.md index ba85a1bd528..f67bca8b9b9 100644 --- a/web/content/docs/devguide/advanced/python-wheel/index.md +++ b/web/content/docs/devguide/advanced/python-wheel/index.md @@ -1,6 +1,6 @@ +++ date = "2022-02-09T11:00:13+01:00" -title = "Python wheel development" +title = "Python bindings development" author = "Lars Bilke" weight = 1068 @@ -9,11 +9,36 @@ weight = 1068 parent = "advanced" +++ -## Local setup +There are two ways to build OGS with Python bindings: -Python wheel builds are driven by [scikit-build](https://scikit-build.readthedocs.io/en/latest/) which basically is a `setuptools`-wrapper for CMake-based projects. +- A regular build with `OGS_USE_PIP=ON` +- A wheel build -The entry point is `setup.py` in the root directory. It uses the `wheel` CMake preset. The preset can be overridden and even other CMake options can be passed via the environment variable `CMAKE_ARGS`. +## Regular build + +- Configure your build with `-DOGS_USE_PIP=ON` +- Build + +To run the Python-based tests: + +- Source `build-dir/.envrc` (activates the virtual environment and sets `OGS_USE_PATH` environment variable) +- Run e.g. `pytest` from inside the source directory. On Windows run `Invoke-Expression build-dir/.envrc.ps1` in your PowerShell. +- Run e.g. `pytest` from inside the source directory or `pytest ../path/to/source/dir`. +- Alternatively you can also run the Python-based with `ctest`, e.g. `ctest -R pytest`. + +If you make modifications on the C++ side you need to run `make` or `ninja` in the build directory again. If you make modifications on the Python bindings you need to run `cmake .` again in the build directory. Modifications on the Python tests are immediately available to `pytest`. + +To get the output of a specific test: + +```bash +pytest --capture=tee-sys ./Tests/Python/test_simulator_mesh_interface.py +``` + +## Wheel build + +Python wheel builds are driven by [scikit-build-core](https://scikit-build-core.readthedocs.io) which basically is a `setuptools`-wrapper for CMake-based projects. + +The entry point is `pyproject.toml` in the root directory. It uses the `wheel` CMake preset. The preset can be overridden and even other CMake options can be passed via the environment variable `CMAKE_ARGS` (see also the [scikit-build-core documentation](https://scikit-build-core.readthedocs.io/en/latest/configuration.html#configuring-cmake-arguments-and-defines)). You can locally develop and test with the following setup: diff --git a/web/content/docs/devguide/packages/python-env/index.md b/web/content/docs/devguide/packages/python-env/index.md index 42e235130ff..82472e21307 100644 --- a/web/content/docs/devguide/packages/python-env/index.md +++ b/web/content/docs/devguide/packages/python-env/index.md @@ -30,7 +30,7 @@ To manually add Python packages run the following inside your build-directory: .venv/bin/pip install python-package-name ``` -To activate the environment run `source .venv/bin/activate` inside your build directory. If you have the [`direnv`](https://direnv.net)-tool installed and setup the virtual environment will be activated automatically upon changing into the build directory. +To activate the environment run `source .envrc` inside your build directory. If you have the [`direnv`](https://direnv.net)-tool installed and setup the virtual environment will be activated automatically upon changing into the build directory. ### Pip & Benchmarks From 85036edd9b0e67b0f2274dea3c67462da309d10f Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 18 Jul 2024 10:15:18 +0200 Subject: [PATCH 05/29] [py] Update ogstools. [py] Use ogstools current master. --- Tests/Data/requirements-dev.txt | 2 +- Tests/Data/requirements.txt | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Tests/Data/requirements-dev.txt b/Tests/Data/requirements-dev.txt index a4011596b5e..529227bcaef 100644 --- a/Tests/Data/requirements-dev.txt +++ b/Tests/Data/requirements-dev.txt @@ -1,4 +1,4 @@ -nbconvert==7.2.9 +nbconvert==7.16.4 nbformat==5.7.3 toml==0.10.2 jupytext==1.14.5 diff --git a/Tests/Data/requirements.txt b/Tests/Data/requirements.txt index 0776610b9de..d4b9c54c57f 100644 --- a/Tests/Data/requirements.txt +++ b/Tests/Data/requirements.txt @@ -1,16 +1,14 @@ --extra-index-url https://gitlab.kitware.com/api/v4/projects/13/packages/pypi/simple -ogstools==0.0.3 +git+https://gitlab.opengeosys.org/ogs/tools/ogstools@b4f3780274c464260ff43a248fac7379e49c8975#egg=ogstools gmsh>=4.11 h5py>=3.8 git+https://github.com/joergbuchwald/heatsource_thm@bbd5bab17fc2ec228c773e087dc847e1ad5f9a4c#egg=heatsource-py jupyterlab==3.4.8 matplotlib>=3.6 numpy<2 -git+https://github.com/joergbuchwald/ogs6py@05acc329b90a002051104af8173384d41c63489c#egg=ogs6py pandas>=1.5 ipywidgets -pyvista[all,jupyter,trame]>=0.39 +pyvista[all]>=0.40.1 seaborn>=0.12 -git+https://github.com/joergbuchwald/VTUinterface@05793c7be84fbcb7d9f8f740c3dc667089a61505#egg=vtuinterface -trame-vtk>=2.4 +VTUinterface>=0.704 vtk-osmesa>=9.2.6;platform_system=='Linux' From 4664dc5b2df00217ce937c0ca0633b69481d7f71 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 18 Jul 2024 10:15:41 +0200 Subject: [PATCH 06/29] [T] Add some ogstools functionality to SimpleMechanics notebook. --- .../Mechanics/Linear/SimpleMechanics.ipynb | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb b/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb index fd1c8ce67fc..827998d4ee0 100644 --- a/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb +++ b/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb @@ -23,7 +23,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 1, "id": "420713a5-74d6-47ad-815c-4ca9e7e914bf", "metadata": { "lines_to_next_cell": 2 @@ -40,7 +40,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 2, "id": "8da3a8e8-be97-4092-88a9-1fb7792fa644", "metadata": { "lines_to_next_cell": 2 @@ -51,8 +51,9 @@ "output_type": "stream", "text": [ "OGS finished with project file _out/SimpleMechanics.prj.\n", - "Execution took 0.09088277816772461 s\n", - "2022-10-19 16:28:18.147773\n" + "Execution took 0.07593870162963867 s\n", + "Project file written to output.\n", + "2024-07-18 09:49:58.202452\n" ] } ], @@ -181,7 +182,7 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 3, "id": "1d730e79", "metadata": { "lines_to_next_cell": 2 @@ -190,16 +191,16 @@ { "data": { "text/plain": [ - "Text(0, 0.5, 'p')" + "Text(0, 0.5, 'u')" ] }, - "execution_count": 26, + "execution_count": 3, "metadata": {}, "output_type": "execute_result" }, { "data": { - "image/png": "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wYOB668HEhOBpl71jYHKzTBQERER1U9VFZCSAnz/vYxu6fXmJqaO2j3ExEhriKbUKjulExERUevn4yNF67aW6r1yxTyatWqVrIF4/jxQUSFrHLYkjlC5AEeoiIiImo9SEraaupC9Id/fXMWHiIiIPJqXV8vfFchARUREROQkBioiIiIiJzFQERERETmJgYqIiIjISQxURERERE5ioCIiIiJyEgMVERERkZMYqIiIiIicxEBFRERE5CQGKiIiIiInMVAREREROYmBioiIiMhJDFRERERETvJp6RNoC5RSAIDCwsIWPhMiIiKqL+P3tvF73BEGKhcoKioCAERHR7fwmRAREVFDFRUVITg42OE+Xqo+sYucYjAYkJWVhcDAQHh5eTXpexcWFiI6OhpnzpxBUFBQk743mfE6uwavs2vwOrsOr7VrNNd1VkqhqKgIkZGR0GgcV0lxhMoFNBoNrrrqqmb9HUFBQfyX1QV4nV2D19k1eJ1dh9faNZrjOtc1MmXEonQiIiIiJzFQERERETmJgcrD+fn5YcGCBfDz82vpU2nVeJ1dg9fZNXidXYfX2jXc4TqzKJ2IiIjISRyhIiIiInISAxURERGRkxioiIiIiJzEQEVERETkJAYqD7B06VJ0794d/v7+iIuLw759+xzuv27dOvTt2xf+/v4YNGgQNm3a5KIz9WwNuc4ffvghrr/+enTs2BEdO3ZEQkJCnX8uJBr699lozZo18PLywuTJk5v3BFuJhl7n/Px8zJkzBxEREfDz80OfPn343456aOh1fuuttxATE4OAgABER0fjscceQ1lZmYvO1jPt3LkTt956KyIjI+Hl5YUNGzbUecyOHTswbNgw+Pn5oXfv3lixYkWznycUubU1a9YorVar/vnPf6qjR4+qBx54QIWEhKjc3Fyb++/evVt5e3urJUuWqGPHjqnnn39e+fr6qsOHD7v4zD1LQ6/zvffeq5YuXaoOHDigjh8/rmbMmKGCg4PV2bNnXXzmnqWh19koLS1NRUVFqeuvv179/ve/d83JerCGXufy8nIVGxurJk6cqHbt2qXS0tLUjh071MGDB1185p6lodd55cqVys/PT61cuVKlpaWpb7/9VkVERKjHHnvMxWfuWTZt2qSee+45tX79egVAff755w73P336tGrXrp2aN2+eOnbsmHrnnXeUt7e32rx5c7OeJwOVmxsxYoSaM2eO6XF1dbWKjIxUixYtsrn/XXfdpSZNmlTjubi4OPXggw8263l6uoZeZ2tVVVUqMDBQffzxx811iq1CY65zVVWVGjVqlFq+fLmaPn06A1U9NPQ6v/fee6pnz56qoqLCVafYKjT0Os+ZM0fdeOONNZ6bN2+euu6665r1PFuT+gSqp556Sg0YMKDGc3fffbdKTExsxjNTilN+bqyiogIpKSlISEgwPafRaJCQkIDk5GSbxyQnJ9fYHwASExPt7k+Nu87WSktLUVlZiU6dOjXXaXq8xl7nl156CWFhYZg5c6YrTtPjNeY6f/nll4iPj8ecOXMQHh6OgQMHYuHChaiurnbVaXucxlznUaNGISUlxTQtePr0aWzatAkTJ050yTm3FS31PcjFkd3YxYsXUV1djfDw8BrPh4eHIzU11eYxOTk5NvfPyclptvP0dI25ztaefvppREZG1vqXmMwac5137dqFf/zjHzh48KALzrB1aMx1Pn36NLZt24YpU6Zg06ZNOHnyJB5++GFUVlZiwYIFrjhtj9OY63zvvffi4sWLGD16NJRSqKqqwkMPPYRnn33WFafcZtj7HiwsLMSVK1cQEBDQLL+XI1RETlq8eDHWrFmDzz//HP7+/i19Oq1GUVERpk6dig8//BBdunRp6dNp1QwGA8LCwvDBBx9g+PDhuPvuu/Hcc89h2bJlLX1qrcqOHTuwcOFCvPvuu9i/fz/Wr1+PjRs34uWXX27pU6MmwBEqN9alSxd4e3sjNze3xvO5ubnQ6XQ2j9HpdA3anxp3nY3eeOMNLF68GFu3bsXgwYOb8zQ9XkOv86lTp5Ceno5bb73V9JzBYAAA+Pj4QK/Xo1evXs170h6oMX+fIyIi4OvrC29vb9Nz/fr1Q05ODioqKqDVapv1nD1RY67zCy+8gKlTp+L+++8HAAwaNAglJSWYNWsWnnvuOWg0HONoCva+B4OCgpptdArgCJVb02q1GD58OJKSkkzPGQwGJCUlIT4+3uYx8fHxNfYHgC1bttjdnxp3nQFgyZIlePnll7F582bExsa64lQ9WkOvc9++fXH48GEcPHjQtN12220YN24cDh48iOjoaFeevsdozN/n6667DidPnjQFVgD49ddfERERwTBlR2Ouc2lpaa3QZAyxisvqNpkW+x5s1pJ3ctqaNWuUn5+fWrFihTp27JiaNWuWCgkJUTk5OUoppaZOnaqeeeYZ0/67d+9WPj4+6o033lDHjx9XCxYsYNuEemjodV68eLHSarXqs88+U9nZ2aatqKiopT6CR2jodbbGu/zqp6HXOTMzUwUGBqq5c+cqvV6vvv76axUWFqZeeeWVlvoIHqGh13nBggUqMDBQrV69Wp0+fVp99913qlevXuquu+5qqY/gEYqKitSBAwfUgQMHFAD1v//7v+rAgQMqIyNDKaXUM888o6ZOnWra39g24cknn1THjx9XS5cuZdsEEu+8847q2rWr0mq1asSIEerHH380vTZmzBg1ffr0Gvt/+umnqk+fPkqr1aoBAwaojRs3uviMPVNDrnO3bt0UgFrbggULXH/iHqahf58tMVDVX0Ov8549e1RcXJzy8/NTPXv2VK+++qqqqqpy8Vl7noZc58rKSvXiiy+qXr16KX9/fxUdHa0efvhhdfnyZdefuAfZvn27zf/eGq/t9OnT1ZgxY2odM2TIEKXValXPnj3VRx991Ozn6aUUxxmJiIiInMEaKiIiIiInMVAREREROYmBioiIiMhJDFRERERETmKgIiIiInISAxURERGRkxioiIiIiJzEQEVERETkJAYqIiIiIicxUBEROWHs2LF49NFHW/o0iKiFMVAREREROYlr+RERNdKMGTPw8ccf13guLS0N3bt3b5kTIqIWw0BFRNRIBQUFmDBhAgYOHIiXXnoJABAaGgpvb+8WPjMicjWflj4BIiJPFRwcDK1Wi3bt2kGn07X06RBRC2INFREREZGTGKiIiIiInMRARUTkBK1Wi+rq6pY+DSJqYQxURERO6N69O/bu3Yv09HRcvHgRBoOhpU+JiFoAAxURkROeeOIJeHt7o3///ggNDUVmZmZLnxIRtQC2TSAiIiJyEkeoiIiIiJzEQEVERETkJAYqIiIiIicxUBERERE5iYGKiIiIyEkMVEREREROYqAiIiIichIDFREREZGTGKiIiIiInMRARUREROQkBioiIiIiJ/0/NTrK4K7j6GgAAAAASUVORK5CYII=", + "image/png": "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ERGRV1OpWv+pQAYqIiIiIhcxUBERERG5iIGKiIiIyEUMVEREREQuYqAiIiIichEDFREREZGLGKiIiIiIXMRARUREROQiBioiIiIiFzFQEREREbmIgYqIiIjIRQxURERERC5ioCIiIiJykU9rD+BqoCgKAKCkpKSVR0JEREQNZfrcNn2O14WByg1KS0sBAHFxca08EiIiImqs0tJS6HS6Os9RKQ2JXeQSo9GInJwchISEQKVSNet7l5SUIC4uDmfOnEFoaGizvjdZ8D67B++ze/A+uw/vtXu01H1WFAWlpaWIiYmBWl13lRRnqNxArVajY8eOLfozQkND+S+rG/A+uwfvs3vwPrsP77V7tMR9rm9myoRF6UREREQuYqAiIiIichEDlZfz8/PDggUL4Ofn19pDadN4n92D99k9eJ/dh/faPTzhPrMonYiIiMhFnKEiIiIichEDFREREZGLGKiIiIiIXMRARUREROQiBiov8Pbbb6NLly7w9/dHQkIC9u/fX+f5a9asQa9eveDv74/+/ftjw4YNbhqpd2vMfX7//fcxevRotGvXDu3atUNSUlK9/1xINPbvs8nq1auhUqlwyy23tOwA24jG3ueioiI88sgjiI6Ohp+fH3r27Mn/djRAY+/zsmXLEB8fj4CAAMTFxeHxxx9HRUWFm0brnXbs2IEbb7wRMTExUKlU+OKLL+q9Zvv27Rg8eDD8/PzQo0cPrFixosXHCYU82urVqxWtVqv861//Un766SflwQcfVMLCwpT8/HyH5+/evVvRaDTK0qVLlePHjyvPP/+84uvrqxw7dszNI/cujb3P99xzj/L2228rhw8fVk6cOKHMmDFD0el0ytmzZ908cu/S2PtskpGRocTGxiqjR49Wbr75ZvcM1os19j5XVlYqQ4cOVSZNmqTs2rVLycjIULZv364cOXLEzSP3Lo29zytXrlT8/PyUlStXKhkZGco333yjREdHK48//ribR+5dNmzYoDz33HPK2rVrFQDKunXr6jz/9OnTSmBgoDJ37lzl+PHjyptvvqloNBpl06ZNLTpOBioPN2zYMOWRRx4xf20wGJSYmBhl8eLFDs+/8847lcmTJ9u8lpCQoDz00EMtOk5v19j7bK+mpkYJCQlRPvzww5YaYpvQlPtcU1OjjBgxQlm+fLkyffp0BqoGaOx9fvfdd5Vu3bopVVVV7hpim9DY+/zII48o119/vc1rc+fOVUaOHNmi42xLGhKonn76aaVv3742r911113KhAkTWnBkisIlPw9WVVWFgwcPIikpyfyaWq1GUlISUlNTHV6Tmppqcz4ATJgwwen51LT7bO/y5cuorq5GeHh4Sw3T6zX1Pr/00kuIjIzE/fff745her2m3OevvvoKiYmJeOSRRxAVFYV+/fph0aJFMBgM7hq212nKfR4xYgQOHjxoXhY8ffo0NmzYgEmTJrllzFeL1voc5ObIHuzixYswGAyIioqyeT0qKgppaWkOr8nLy3N4fl5eXouN09s15T7be+aZZxATE1PrX2KyaMp93rVrF/75z3/iyJEjbhhh29CU+3z69Gls3boVU6dOxYYNG3Dq1Ck8/PDDqK6uxoIFC9wxbK/TlPt8zz334OLFixg1ahQURUFNTQ3+9Kc/4dlnn3XHkK8azj4HS0pKcOXKFQQEBLTIz+UMFZGLlixZgtWrV2PdunXw9/dv7eG0GaWlpZg2bRref/99dOjQobWH06YZjUZERkbiH//4B4YMGYK77roLzz33HJKTk1t7aG3K9u3bsWjRIrzzzjs4dOgQ1q5di/Xr1+Pll19u7aFRM+AMlQfr0KEDNBoN8vPzbV7Pz8+HXq93eI1er2/U+dS0+2zy2muvYcmSJdiyZQsGDBjQksP0eo29z7/88gsyMzNx4403ml8zGo0AAB8fH6Snp6N79+4tO2gv1JS/z9HR0fD19YVGozG/1rt3b+Tl5aGqqgparbZFx+yNmnKf//znP2PatGl44IEHAAD9+/dHeXk5Zs6cieeeew5qNec4moOzz8HQ0NAWm50COEPl0bRaLYYMGYKUlBTza0ajESkpKUhMTHR4TWJios35ALB582an51PT7jMALF26FC+//DI2bdqEoUOHumOoXq2x97lXr144duwYjhw5Yj5uuukmjBs3DkeOHEFcXJw7h+81mvL3eeTIkTh16pQ5sALAzz//jOjoaIYpJ5pyny9fvlwrNJlCrMJtdZtNq30OtmjJO7ls9erVip+fn7JixQrl+PHjysyZM5WwsDAlLy9PURRFmTZtmjJv3jzz+bt371Z8fHyU1157TTlx4oSyYMECtk1ogMbe5yVLliharVb5/PPPldzcXPNRWlraWr+CV2jsfbbHp/waprH3OTs7WwkJCVFmz56tpKenK19//bUSGRmp/PWvf22tX8ErNPY+L1iwQAkJCVE++eQT5fTp08q3336rdO/eXbnzzjtb61fwCqWlpcrhw4eVw4cPKwCUv//978rhw4eVrKwsRVEUZd68ecq0adPM55vaJjz11FPKiRMnlLfffpttE0i8+eabSqdOnRStVqsMGzZM2bt3r/l7Y8aMUaZPn25z/meffab07NlT0Wq1St++fZX169e7ecTeqTH3uXPnzgqAWseCBQvcP3Av09i/z9YYqBqusfd5z549SkJCguLn56d069ZNWbhwoVJTU+PmUXufxtzn6upq5YUXXlC6d++u+Pv7K3FxccrDDz+sFBYWun/gXmTbtm0O/3trurfTp09XxowZU+uagQMHKlqtVunWrZvywQcftPg4VYrCeUYiIiIiV7CGioiIiMhFDFRERERELmKgIiIiInIRAxURERGRixioiIiIiFzEQEVERETkIgYqIiIiIhcxUBERERG5iIGKiIiIyEUMVERELhg7diwee+yx1h4GEbUyBioiIiIiF3EvPyKiJpoxYwY+/PBDm9cyMjLQpUuX1hkQEbUaBioioiYqLi7GxIkT0a9fP7z00ksAgIiICGg0mlYeGRG5m09rD4CIyFvpdDpotVoEBgZCr9e39nCIqBWxhoqIiIjIRQxURERERC5ioCIicoFWq4XBYGjtYRBRK2OgIiJyQZcuXbBv3z5kZmbi4sWLMBqNrT0kImoFDFRERC548sknodFo0KdPH0RERCA7O7u1h0RErYBtE4iIiIhcxBkqIiIiIhcxUBERERG5iIGKiIiIyEUMVEREREQuYqAiIiIichEDFREREZGLGKiIiIiIXMRARUREROQiBioiIiIiFzFQEREREbmIgYqIiIjIRf8P1J+7j7ZvJFEAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -266,10 +267,56 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "id": "9d8111eb-c60a-4676-bcac-e9b2f35af38c", "metadata": {}, "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "\n", + "import ogstools as ot\n", + "from ogstools import examples\n", + "from ogstools.meshlib import MeshSeries" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "id": "2b34c5da-d928-4cd7-8908-12c8dd44c089", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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Yc+ePZg4cSIOHDiAoUOH1qjLcRwGDBjA3M/rr78elZWVmDhxYshHVVUVbrjhhhp1W7dujZEjR9YonzhxItauXYv9+/dj3bp1GDt2LAYOHIj8/PyIegcOHADHcTW+BrVarbj11lsxa9YsbNiwARs2bMCsWbNw2223hQ6JjYeStZGUG6aFCxeiVatWcDgc6N27N3744YeY9ZctW4a8vDw4HA4UFBRg5cqVode8Xi8eeughFBQUID09HU2bNsXo0aNx+PDhiDZatWpV44yRJ598UtO4AmEn8+qKoy7Qazxw53fwj1kJvuC64P8tf00kvxdYPR04tlfzvhptpwazxEja6GdrpD/SJnm56667MGHCBIwbNw79+/dHQUEBXnrpJUP74HA48Nlnn+HgwYPo3r07Xn31VSxduhSdOnWS3UYgEMCDDz6ILl26oG/fvvjxxx/x6aefokePHhH1hCtOOTk5zP3MycnBp59+irVr16Jbt25Yt24dPv30U6avwn7//XeMHDkSubm5GDNmDC644AK8//77NerF6uesWbNw1VVXhR7Dhg3DzJkzZfdB0VxVfBCCTixdupS32+384sWL+d27d/Pjx4/ns7Ky+KNHj4rW37hxI2+1Wvmnn36a37NnDz9t2jTeZrPxO3fu5Hk+eILnwIED+ffee48vKiriCwsL+V69evE9evSIaKdly5b8448/zh85ciT0qKiokN1vOecwCScSs6D2rCFRn7s+PnOu02uDef5/7/O8t1p1X42200WbWmLH8+rP0zFDjEbPHdImtj+znvR9trFy5Uqe4zj+f//7X6K7EpMXX3yRdzqdfElJieq2os9hCl8bcs9hSrorTHPnzsX48eMxduxYdOjQAYsWLYLT6cTixYtF68+fPx+DBw/GlClTkJ+fjyeeeALdu3fHggULAARPPl29ejWuu+465Obm4vzzz8eCBQuwZcsWHDx4MKKtzMxM5OTkhB5K7v43BVnNgbwrAM4KHPwO+OhWYG5+8KrTif2J7h1BEAShI2vXrsWIESPQuXPnRHclJmvXrsV9992Hxo0bJ7orAJLsV3IejwdbtmwJ/VIBCN7xP3DgQBQWForaFBYWYtKkSRFlgwYNwvLlyyX9lJWVgeO4GodkPfnkk3jiiSfQokULXH/99Zg4cSJSUsQlcrvdEYkoy8vLAQB+v180USv/V4Zkv9/P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RHdNVwKBACZMmIALLrgAnTp1kqx3trznhCNXm7PpPWfnzp3IyMhAamoq7rjjDnz88cfo0KGDaN3aOmdSEt0BgtCKPn36RPzF07dvX+Tn5+Pll1/GE088kcCeEclMbm4ucnNzQ//v27cvfvnlFzz33HN48803E9gzfbn77ruxa9cufPvtt4nuStIhV5uz6T0nNzcX27dvR1lZGT744AOMGTMGGzZskNw01UboClMCyc7OhtVqxdGjRyPKjx49ipycHFGbnJwcpvpmRYk20dhsNnTr1g0///yzHl00FVLzpk6dOkhLS0tQr5KXXr161ep5c8899+Czzz7DunXr0KxZs5h1z5b3HAEWbaKpze85drsdbdu2RY8ePTB79mx06dIF8+fPF61bW+cMbZgSiN1uR48ePbBmzZpQWSAQwJo1ayS/G+7Tp09EfQBYvXq1ZH2zokSbaPx+P3bu3IkmTZro1U3TcLbMG63Yvn17rZw3PM/jnnvuwccff4y1a9eidevWcW3OlrmjRJtozqb3nEAgALfbLfparZ0zib7r/Gxn6dKlfGpqKv/666/ze/bs4W+77TY+KyuLLykp4Xme52+66Sb+4YcfDtXfuHEjn5KSwj/77LP83r17+RkzZvA2m43fuXNnokLQDVZtZs6cyX/xxRf8L7/8wm/ZsoUfOXIk73A4+N27dycqBN04ffo0v23bNn7btm08AH7u3Ln8tm3b+N9++43neZ5/+OGH+ZtuuilU/9dff+WdTic/ZcoUfu/evfzChQt5q9XKr1q1KlEh6AarNs899xy/fPly/qeffuJ37tzJ33///bzFYuG/+uqrRIWgG3feeSdft25dfv369fyRI0dCj8rKylCds/U9R4k2Z8t7zsMPP8xv2LCB379/P79jxw7+4Ycf5jmO47/88kue58+eOUMbpiTghRde4Fu0aMHb7Xa+V69e/Pfffx96rX///vyYMWMi6r///vt8+/btebvdznfs2JH//PPPDe6xcbBoM2HChFDdxo0b85dffjm/devWBPRaf4Sfwkc/BD3GjBnD9+/fv4ZN165debvdzrdp04ZfsmSJ4f02AlZtnnrqKf7cc8/lHQ4HX79+fX7AgAH82rVrE9N5nRHTBUDEXDhb33OUaHO2vOfccsstfMuWLXm73c43bNiQv+SSS0KbJZ4/e+YMx/M8b9z1LIIgCIIg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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "mesh_series = MeshSeries(f\"{out_dir}/{prj_name}.pvd\")\n", + "points = np.asarray(\n", + " [[0.3, 0.5, 0.0], [0.24, 0.21, 0.0]]\n", + ")\n", + "disp = ot.properties.displacement\n", + "\n", + "labels = [f\"{i}: {label}\" for i, label in enumerate(ot.plot.utils.justified_labels(points))]\n", + "fig = mesh_series.plot_probe(\n", + " points=points[:4], mesh_property=disp,\n", + " time_unit=\"a\", labels=labels[:4]\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c0b40718-8f69-4d02-83db-71a7e25ece3a", + "metadata": {}, + "outputs": [], "source": [] } ], @@ -289,7 +336,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.2" + "version": "3.11.8" }, "vscode": { "interpreter": { From 80236ce9ccea05360e1b28a828f27e2fcb72b621 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 18 Jul 2024 10:37:12 +0200 Subject: [PATCH 07/29] [T] Adapt msh2vtu usage in notebooks. See https://gitlab.opengeosys.org/ogs/tools/ogstools/-/merge_requests/123: `--ogs` --> `--keep_ids` --- .../SeabedResponse/Stationary_waves.ipynb | 7 +++++-- .../SeabedResponse/seabed_response_200x100.prj | 2 +- ...r_Disc_with_hole_convergence_analysis.ipynb | 14 ++++++++++---- .../Kregime_Propagating_jupyter.ipynb | 18 ++++++++---------- .../Kregime_Static_jupyter.ipynb | 2 +- scripts/ci/jobs/jupyter.yml | 2 +- 6 files changed, 26 insertions(+), 19 deletions(-) diff --git a/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb b/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb index 500d30a44b4..6b545dde586 100644 --- a/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb +++ b/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb @@ -742,8 +742,11 @@ } ], "source": [ - "!msh2vtu --ogs {input_file}\n", - "assert _exit_code == 0 # noqa: F821" + "!msh2vtu --keep_ids -r -o {out_dir} {input_file}\n", + "assert _exit_code == 0 # noqa: F821\n", + "%cd {out_dir}\n", + "!identifySubdomains -f -m square_200x100_domain.vtu -- square_200x100_physical_group_*.vtu\n", + "%cd -" ] }, { diff --git a/Tests/Data/HydroMechanics/SeabedResponse/seabed_response_200x100.prj b/Tests/Data/HydroMechanics/SeabedResponse/seabed_response_200x100.prj index 3e02cf700a4..759302ac240 100644 --- a/Tests/Data/HydroMechanics/SeabedResponse/seabed_response_200x100.prj +++ b/Tests/Data/HydroMechanics/SeabedResponse/seabed_response_200x100.prj @@ -28,7 +28,7 @@ - + Gas diff --git a/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb b/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb index 4233098faae..0415bdf182a 100644 --- a/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb +++ b/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb @@ -569,7 +569,13 @@ "source": [ "for idx in STUDY_indices:\n", " input_file = f\"{out_dir}/disc_with_hole_idx_is_{idx}.msh\"\n", - " ! msh2vtu -r --ogs -o {out_dir}/disc_with_hole_idx_is_{idx} {input_file}" + " msh2vtu_out_dir = Path(f\"{out_dir}/disc_with_hole_idx_is_{idx}\")\n", + " if not msh2vtu_out_dir.exists():\n", + " msh2vtu_out_dir.mkdir(parents=True)\n", + " ! msh2vtu -r --keep_ids -o {out_dir}/disc_with_hole_idx_is_{idx} {input_file}\n", + " %cd {out_dir}/disc_with_hole_idx_is_{idx}\n", + " ! identifySubdomains -f -m disc_with_hole_idx_is_{idx}_domain.vtu -- disc_with_hole_idx_is_{idx}_physical_group_*.vtu\n", + " %cd -" ] }, { @@ -633,8 +639,8 @@ } ], "source": [ - "domain_8 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_8_\" + \"domain.vtu\")\n", - "domain_80 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_80_\" + \"domain.vtu\")\n", + "domain_8 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_8/disc_with_hole_idx_is_8_domain.vtu\")\n", + "domain_80 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_80/disc_with_hole_idx_is_80_domain.vtu\")\n", "\n", "p = pv.Plotter(shape=(1, 2), border=False)\n", "p.subplot(0, 0)\n", @@ -721,7 +727,7 @@ " prj_path = out_dir / prj_file\n", "\n", " model = ogs.OGS(INPUT_FILE=prj_path, PROJECT_FILE=prj_path)\n", - " model.run_model(logfile=f\"{out_dir}/out.txt\", args=f\"-o {out_dir}\")" + " model.run_model(logfile=f\"{out_dir}/out.txt\", args=f\"-o {out_dir} -m {out_dir}/disc_with_hole_idx_is_{idx}\")" ] }, { diff --git a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb index d53861a1a65..d7cf2909b51 100644 --- a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb +++ b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb @@ -143,7 +143,7 @@ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "from ogs6py import ogs\n", - "from ogstools.msh2vtu import run\n", + "from ogstools.msh2vtu import msh2vtu\n", "\n", "pi = math.pi\n", "plt.rcParams[\"text.usetex\"] = True" @@ -363,17 +363,15 @@ " mesh_generation(0.1, h)\n", " # Convert GMSH (.msh) meshes to VTU meshes appropriate for OGS simulation.\n", " input_file = f\"{out_dir}/\" + meshname + \".msh\"\n", - " args = argparse.Namespace(\n", + " msh2vtu(\n", " filename=input_file,\n", - " output=f\"{out_dir}/\" + meshname,\n", - " dim=0,\n", - " delz=False,\n", - " swapxy=False,\n", - " rdcd=True,\n", - " ogs=True,\n", - " ascii=False,\n", + " output_path=out_dir,\n", + " reindex=True,\n", + " keep_ids=True\n", " )\n", - " run(args)\n", + " %cd {out_dir}\n", + " ! identifySubdomains -f -m mesh_full_pf_domain.vtu -- mesh_full_pf_physical_group_*.vtu\n", + " %cd -\n", "\n", " # As a preprocessing step, define the initial phase-field (crack).\n", " pre_processing(h, a0)\n", diff --git a/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb b/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb index 6a16ed8d16c..a79093c6081 100644 --- a/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb +++ b/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb @@ -307,7 +307,7 @@ " mesh_generation(0.1, h)\n", " # Convert GMSH (.msh) meshes to VTU meshes appropriate for OGS simulation.\n", " input_file = f\"{out_dir}/\" + meshname + \".msh\" # noqa: F841\n", - " ! msh2vtu --ogs -o {out_dir}/{meshname} {input_file}\n", + " ! msh2vtu --keep_ids -o {out_dir} {input_file}\n", " # As a preprocessing step, define the initial phase-field (crack).\n", " pre_processing(h, a0)\n", " # change properties in prj file #For more information visit: https://github.com/joergbuchwald/ogs6py\n", diff --git a/scripts/ci/jobs/jupyter.yml b/scripts/ci/jobs/jupyter.yml index 30d10948abb..6b4571e54ef 100644 --- a/scripts/ci/jobs/jupyter.yml +++ b/scripts/ci/jobs/jupyter.yml @@ -15,7 +15,7 @@ test notebooks via wheel: - | cd ../../web/content/docs/tutorials/advancing-glacier python mesh_basin.py - msh2vtu mesh_basin.msh --ogs --rdcd + msh2vtu mesh_basin.msh --reindex ogs OGSinput_basin.prj cd - # Append mtest install directory to PYTHONPATH From 89619bad75d0ce21dd901dfc6b21581a5603f6c8 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 25 Jul 2024 09:59:19 +0200 Subject: [PATCH 08/29] [py] Better handling of cli flags in Python wrapper. CLI flags without additional value can now be given with e.g.: cli.GMSH2OGS(gmsh2_physical_id=True) # or gmsh2_physical_id=None cli.GMSH2OGS(gmsh2_physical_id=False) # disables the flag. --- .../Python/ogs/_internal/wrap_cli_tools.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Applications/Python/ogs/_internal/wrap_cli_tools.py b/Applications/Python/ogs/_internal/wrap_cli_tools.py index db41495f4c7..c571b025d1a 100644 --- a/Applications/Python/ogs/_internal/wrap_cli_tools.py +++ b/Applications/Python/ogs/_internal/wrap_cli_tools.py @@ -32,7 +32,7 @@ def ogs(self, *args, **kwargs): >>> cli = CLI() >>> cli.ogs("--help") # prints a help text ... - >>> cli.ogs(help=None) # special, does the same + >>> cli.ogs(help=True) # flags without any additional value can be set to True ... A more useful example. The following will create a line mesh: @@ -52,12 +52,25 @@ def ogs(self, *args, **kwargs): @staticmethod def _format_kv(kwargs): for key, v in kwargs.items(): + # Convert None to True + if v is None: + # TODO: Remove after 2025/08 + print( + f"Deprecation warning: Setting {v} to `None` is deprecated, set to `True` instead!" + ) + v = True # noqa: PLW2901 + + # If value is False then ignore + if isinstance(v, bool) and not v: + continue + if len(key) == 1: yield f"-{key}" else: yield f"--{key}" - if v is not None: + # Pass value if not bool + if not isinstance(v, bool): yield f"{v}" @staticmethod @@ -74,6 +87,7 @@ def run_cmd(*args, **kwargs): cmdline = CLI._get_cmdline(cmd, *args, **kwargs) return subprocess.call(cmdline) + # TODO: Only arguments with underscores work. Arguments with dashes not. run_cmd.__doc__ = f""" This function wraps the commandline tool {attr} for easy use from Python. @@ -89,7 +103,7 @@ def run_cmd(*args, **kwargs): >>> cli = CLI() >>> cli.{attr}("--help") # prints a help text ... - >>> cli.{attr}(help=None) # special, does the same + >>> cli.ogs(help=True) # flags without any additional value can be set to True ... A more useful example. The following will create a line mesh: From 0c7dd4803e295385abd3ae3a3d625092eb05224f Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 23 Jul 2024 14:59:41 +0200 Subject: [PATCH 09/29] [cmake,py] Removed snakemake setup. --- scripts/cmake/Find.cmake | 6 --- scripts/cmake/PythonSetup.cmake | 14 ++--- scripts/cmake/test/Test.cmake | 12 ++--- scripts/snakemake/modules/meshes.smk | 10 ---- scripts/snakemake/vtkdiff/environment.yaml | 2 - scripts/snakemake/vtkdiff/wrapper.py | 34 ------------ scripts/snakemake/workflows/partmesh.smk | 8 --- scripts/test/buildinfo.in.yaml | 5 -- .../testing/workflow-testing/index.md | 53 ------------------- web/data/versions.json | 2 - 10 files changed, 7 insertions(+), 139 deletions(-) delete mode 100644 scripts/snakemake/modules/meshes.smk delete mode 100644 scripts/snakemake/vtkdiff/environment.yaml delete mode 100644 scripts/snakemake/vtkdiff/wrapper.py delete mode 100644 scripts/snakemake/workflows/partmesh.smk delete mode 100644 scripts/test/buildinfo.in.yaml delete mode 100644 web/content/docs/devguide/testing/workflow-testing/index.md diff --git a/scripts/cmake/Find.cmake b/scripts/cmake/Find.cmake index e2616a71a2e..4af819824d8 100644 --- a/scripts/cmake/Find.cmake +++ b/scripts/cmake/Find.cmake @@ -26,12 +26,6 @@ find_program(CCACHE_TOOL_PATH ccache) find_program(MODULE_CMD lmod PATHS /software/lmod/lmod/libexec) -find_program(SNAKEMAKE snakemake) -find_program(TEE_TOOL_PATH tee) -if(OGS_BUILD_TESTING AND SNAKEMAKE AND NOT TEE_TOOL_PATH) - message(WARNING "tee tool was not found. Snakemake tests are disabled!") -endif() - find_program(GMSH gmsh) find_program(XMLSTARLET_TOOL_PATH xmlstarlet) diff --git a/scripts/cmake/PythonSetup.cmake b/scripts/cmake/PythonSetup.cmake index 329e35ce546..fb22b42ee2e 100644 --- a/scripts/cmake/PythonSetup.cmake +++ b/scripts/cmake/PythonSetup.cmake @@ -92,15 +92,8 @@ if(OGS_USE_PIP) file(STRINGS Tests/Data/requirements-dev.txt _requirements_dev) list(APPEND OGS_PYTHON_PACKAGES ${_requirements} ${_requirements_dev}) - list( - APPEND - OGS_PYTHON_PACKAGES - "snakemake==${ogs.minimum_version.snakemake}" - "pulp==2.7.0" # https://github.com/snakemake/snakemake/issues/2607 - "setuptools" # https://github.com/glenfant/stopit/issues/32 - ) - set(SNAKEMAKE ${LOCAL_VIRTUALENV_BIN_DIR}/snakemake CACHE FILEPATH "" - FORCE + list(APPEND OGS_PYTHON_PACKAGES + "setuptools" # https://github.com/glenfant/stopit/issues/32 ) endif() endif() @@ -209,8 +202,7 @@ function(setup_venv_dependent_ctests) PATH Parabolic/HT/InvalidProjectFiles EXECUTABLE ogs EXECUTABLE_ARGS ${ht_invalid_prj_file} - RUNTIME 1 - PROPERTIES WILL_FAIL TRUE + RUNTIME 1 PROPERTIES WILL_FAIL TRUE ) endforeach() endif() diff --git a/scripts/cmake/test/Test.cmake b/scripts/cmake/test/Test.cmake index ef7d99790e6..1c70e13a9ff 100644 --- a/scripts/cmake/test/Test.cmake +++ b/scripts/cmake/test/Test.cmake @@ -84,18 +84,14 @@ set_target_properties( Testing ) -configure_file( - ${PROJECT_SOURCE_DIR}/scripts/test/buildinfo.in.yaml - ${PROJECT_BINARY_DIR}/buildinfo.yaml -) - file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/logs) # Files in Testing/Notes are submitted to cdash, supply additional build info. if(DEFINED ENV{CI_JOB_URL}) - file(GENERATE OUTPUT ${PROJECT_BINARY_DIR}/Testing/Notes/buildinfo.txt - CONTENT -"CI_JOB_URL=$ENV{CI_JOB_URL} + file( + GENERATE + OUTPUT ${PROJECT_BINARY_DIR}/Testing/Notes/buildinfo.txt + CONTENT "CI_JOB_URL=$ENV{CI_JOB_URL} COMMIT_URL=$ENV{CI_PROJECT_URL}/-/commit/$ENV{CI_COMMIT_SHA} CI_COMMIT_TIMESTAMP=$ENV{CI_COMMIT_TIMESTAMP}\n" ) diff --git a/scripts/snakemake/modules/meshes.smk b/scripts/snakemake/modules/meshes.smk deleted file mode 100644 index 4d24e8e02cc..00000000000 --- a/scripts/snakemake/modules/meshes.smk +++ /dev/null @@ -1,10 +0,0 @@ -rule generate_square_mesh: - output: - "{mesh_name_prefix,\\w+}_{size,\\d+}_{lx,\\d+}x{ly,\\d+}_{type}.vtu" - shell: - """ - generateStructuredMesh -e {wildcards.type} \ - --lx {wildcards.lx} --ly {wildcards.ly} \ - --nx {wildcards.size} --ny {wildcards.size} \ - -o {output} - """ diff --git a/scripts/snakemake/vtkdiff/environment.yaml b/scripts/snakemake/vtkdiff/environment.yaml deleted file mode 100644 index bc29b1f14d4..00000000000 --- a/scripts/snakemake/vtkdiff/environment.yaml +++ /dev/null @@ -1,2 +0,0 @@ -dependencies: - - python diff --git a/scripts/snakemake/vtkdiff/wrapper.py b/scripts/snakemake/vtkdiff/wrapper.py deleted file mode 100644 index 78d3902da57..00000000000 --- a/scripts/snakemake/vtkdiff/wrapper.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Snakemake wrapper for vtkdiff.""" - -__author__ = "Lars Bilke" -__copyright__ = "Copyright 2020, OpenGeoSys Community" -__license__ = "BSD" - -from pathlib import Path - -from snakemake.shell import shell - -# ruff: noqa: F821 -output = Path(snakemake.output[0]) -if output.exists(): - output.unlink() - -if snakemake.params.check_mesh: - shell("vtkdiff {snakemake.input.a} {snakemake.input.b} -m > {snakemake.output[0]}") - -for field in snakemake.params.fields: - field_a = field[0] - offset = 0 - if len(field) == 4: - offset = 1 - field_b = field[0 + offset] - abs_tol = field[1 + offset] - rel_tol = field[2 + offset] - - shell( - """ - vtkdiff {snakemake.input.a} {snakemake.input.b} \ - -a {field_a} -b {field_b} \ - --abs {abs_tol} --rel {rel_tol} 2>&1 | tee -a {snakemake.output[0]} - """ - ) diff --git a/scripts/snakemake/workflows/partmesh.smk b/scripts/snakemake/workflows/partmesh.smk deleted file mode 100644 index dcb674cb810..00000000000 --- a/scripts/snakemake/workflows/partmesh.smk +++ /dev/null @@ -1,8 +0,0 @@ -from snakemake.utils import min_version -min_version("7.3") - -module partmesh: - snakefile: gitlab("bilke/snakemake-partmesh", path="workflow/Snakefile", tag="bbcdc9a721fcda7a1e9619895dce79dfc2b2c905", host="gitlab.opengeosys.org") - config: config - -use rule * from partmesh diff --git a/scripts/test/buildinfo.in.yaml b/scripts/test/buildinfo.in.yaml deleted file mode 100644 index 04322b42cd0..00000000000 --- a/scripts/test/buildinfo.in.yaml +++ /dev/null @@ -1,5 +0,0 @@ -SOURCE_DIR: "@PROJECT_SOURCE_DIR@" -BUILD_DIR: "@PROJECT_BINARY_DIR@" -BIN_DIR: "@PROJECT_BINARY_DIR@/bin" -Data_SOURCE_DIR: "@PROJECT_SOURCE_DIR@/Tests/Data" -Data_BINARY_DIR: "@PROJECT_BINARY_DIR@/Tests/Data" diff --git a/web/content/docs/devguide/testing/workflow-testing/index.md b/web/content/docs/devguide/testing/workflow-testing/index.md deleted file mode 100644 index ac6d8798973..00000000000 --- a/web/content/docs/devguide/testing/workflow-testing/index.md +++ /dev/null @@ -1,53 +0,0 @@ -+++ -date = "2021-03-05T10:49" -title = "Workflow testing" -author = "Lars Bilke" -weight = 1024 - -[menu] - [menu.devguide] - parent = "testing" -+++ - -## Introduction - -We use the workflow manager [Snakemake](https://snakemake.readthedocs.io) to test workflows which consist of the execution of several steps which are based on each other. - -## Requirements - -- [Snakemake](https://snakemake.readthedocs.io/en/stable/getting_started/installation.html) >= {{< dataFile "versions.minimum_version.snakemake" >}} - - If you use `OGS_USE_PIP=ON` then `snakemake` is installed in your virtual environment in your build-directory automatically. You can then call it via `.venv/bin/snakemake ...` (inside your build directory). -- On Windows only: - - The `tee`-utility in the `PATH` (can be installed from ) - -## Examples - -- [ExtractBoundary.smk](https://gitlab.opengeosys.org/ogs/ogs/-/blob/master/Applications/Utils/ExtractBoundary.smk) -- [VoxelGridFromLayers.smk](https://gitlab.opengeosys.org/ogs/ogs/-/blob/master/Applications/Utils/VoxelGridFromLayers.smk) - -These example workflows [are added to CTest](https://gitlab.opengeosys.org/ogs/ogs/-/blob/540d0b454c9e3805a81f7c4a1b6ee7565be6845c/Applications/Utils/Tests.cmake#L302-315) as well: - -```cmake -if(SNAKEMAKE AND NOT OGS_USE_MPI) - add_test(NAME snakemake_ExtractBoundary - COMMAND ${SNAKEMAKE} -j 1 - --configfile ${PROJECT_BINARY_DIR}/buildinfo.yaml - -s ${CMAKE_CURRENT_SOURCE_DIR}/ExtractBoundary.smk - ) - add_test(NAME snakemake_VoxelGridFromLayers - # ... - ) - add_dependencies(ctest ExtractBoundary Layers2Grid AddFaultToVoxelGrid) -endif() -``` - -## Modularization - -We started on implementing modular rule definitions and tool wrapper in [`scripts/snakemake`](https://gitlab.opengeosys.org/ogs/ogs/-/tree/master/scripts/snakemake). - -## Links - -- [Snakemake Documentation](https://snakemake.readthedocs.io) -- [Short tutorial](https://snakemake.readthedocs.io/en/stable/tutorial/short.html) -- [Software Carpentry Workshop](https://carpentries-incubator.github.io/workflows-snakemake/index.html) -- [HPC Carpentry Workshop with Snakemake](http://www.hpc-carpentry.org/hpc-python/) diff --git a/web/data/versions.json b/web/data/versions.json index 0e7e9b31a06..e057bbe7d17 100644 --- a/web/data/versions.json +++ b/web/data/versions.json @@ -19,7 +19,6 @@ "petsc": "3.18.6", "qt": "5.14.2", "python": "3.9", - "snakemake": "8.2.4", "hdf5": "1.10.7", "libxml2": "2.9.12", "tfel-rliv": "4.0", @@ -45,7 +44,6 @@ "python": { "jupyter_image": { "conda_packages": [ - "snakemake-minimal", "pyvista==0.34.2", "ipyvtklink", "pythreejs" From dfeed3aa265e9e7688a43bcb32e43fff15e51cb1 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 23 Jul 2024 16:12:13 +0200 Subject: [PATCH 10/29] [T] Added test_partmesh_mixed_elements. --- Applications/Utils/Tests.cmake | 11 ------ .../GMSH2OGS/test_partmesh_mixed_elements.py | 37 +++++++++++++++++++ 2 files changed, 37 insertions(+), 11 deletions(-) create mode 100644 Tests/Data/Utils/GMSH2OGS/test_partmesh_mixed_elements.py diff --git a/Applications/Utils/Tests.cmake b/Applications/Utils/Tests.cmake index e4509187dbf..2113161ab35 100644 --- a/Applications/Utils/Tests.cmake +++ b/Applications/Utils/Tests.cmake @@ -531,17 +531,6 @@ AddTest( ################################################ -if(SNAKEMAKE AND TEE_TOOL_PATH AND BASH_TOOL_PATH) - add_test(NAME snakemake_partmesh_mixed_elements - COMMAND bash -c "export PATH=$:$PATH && ${SNAKEMAKE} -j 4 \ - --config input_dir=${Data_SOURCE_DIR}/Utils/GMSH2OGS \ - -s ${PROJECT_SOURCE_DIR}/scripts/snakemake/workflows/partmesh.smk \ - ${Data_BINARY_DIR}/Utils/GMSH2OGS/{linear,quadratic}_mesh/{2,4,8,12}" - ) - set_tests_properties(snakemake_partmesh_mixed_elements - PROPERTIES LABELS "default") -endif() - if(SNAKEMAKE AND TEE_TOOL_PATH AND BASH_TOOL_PATH AND OGS_USE_MPI) add_test(NAME snakemake_reorder_mesh COMMAND bash -c "${SNAKEMAKE} -j 4 \ diff --git a/Tests/Data/Utils/GMSH2OGS/test_partmesh_mixed_elements.py b/Tests/Data/Utils/GMSH2OGS/test_partmesh_mixed_elements.py new file mode 100644 index 00000000000..c6b8e4dfee0 --- /dev/null +++ b/Tests/Data/Utils/GMSH2OGS/test_partmesh_mixed_elements.py @@ -0,0 +1,37 @@ +import itertools +import os +import tempfile +from pathlib import Path + +from ogs import cli + + +def test_partmesh_mixed_elements(): + os.chdir(Path(__file__).resolve().parent) + + meshes = ["linear", "quadratic"] + partitions = [2, 4, 8, 12] + + for mesh, partition in itertools.product(meshes, partitions): + with tempfile.TemporaryDirectory() as tmpdirname: + cli.partmesh(ogs2metis=None, i=f"{mesh}_mesh.vtu", o=tmpdirname) + assert Path(f"{tmpdirname}/{mesh}_mesh.mesh").exists() + + cli.partmesh( + exe_metis=None, + i=f"{mesh}_mesh.vtu", + x=f"{tmpdirname}/{mesh}_mesh", + o=tmpdirname, + np=partition, + ) + for filetype in [ + "cell_properties_cfg", + "cell_properties_val", + "msh_cfg", + "msh_ele_g", + "msh_ele", + "msh_nod", + ]: + assert Path( + f"{tmpdirname}/{mesh}_mesh_partitioned_{filetype}{partition}.bin" + ).exists() From 9e78d061e46cbb3584be3d235f6499fc73b45d13 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 24 Jul 2024 09:50:53 +0200 Subject: [PATCH 11/29] [T] Rewritten ExtractBoundary snakemake test to pytest. --- Applications/Utils/ExtractBoundary.smk | 44 ------------------- Applications/Utils/Tests.cmake | 16 +------ .../square_10_1x1_quad_boundary.vtu | 0 .../square_10_1x1_tri_boundary.vtu | 0 .../ExtractBoundary/test_extract_boundary.py | 39 ++++++++++++++++ 5 files changed, 40 insertions(+), 59 deletions(-) delete mode 100644 Applications/Utils/ExtractBoundary.smk rename Tests/Data/{FileIO => Utils/ExtractBoundary}/square_10_1x1_quad_boundary.vtu (100%) rename Tests/Data/{FileIO => Utils/ExtractBoundary}/square_10_1x1_tri_boundary.vtu (100%) create mode 100644 Tests/Data/Utils/ExtractBoundary/test_extract_boundary.py diff --git a/Applications/Utils/ExtractBoundary.smk b/Applications/Utils/ExtractBoundary.smk deleted file mode 100644 index 687dd36cad0..00000000000 --- a/Applications/Utils/ExtractBoundary.smk +++ /dev/null @@ -1,44 +0,0 @@ -# Usage, e.g.: -# snakemake -s ExtractBoundary.smk -j 1 --configfile $HOME/code/ogs6/build/buildinfo.yaml -# -# buildinfo.yaml contains variables such as Data_BINARY_DIR - -output_path = "FileIO" - -import os -os.environ["PATH"] += os.pathsep + os.pathsep.join([config['BIN_DIR']]) -workdir: f"{config['Data_BINARY_DIR']}/{output_path}" - -# "entry point", otherwise one would had to specify output files as snakemake -# arguments -elem_types = ['tri', 'quad'] -rule all: - input: - expand("square_10_1x1_{type}_boundary_diff.out", type=elem_types) - -include: f"{config['SOURCE_DIR']}/scripts/snakemake/modules/meshes.smk" - -rule extract_boundary: - input: - rules.generate_square_mesh.output - output: - "{mesh_name_prefix}_{size}_{lx}x{ly}_{type}_boundary.vtu" - shell: - "ExtractBoundary -i {input} -o {output}" - -rule vtkdiff: - input: - a = rules.extract_boundary.output, - b = f"{config['Data_SOURCE_DIR']}/{output_path}/{rules.extract_boundary.output}" - output: - "{mesh_name_prefix}_{size}_{lx}x{ly}_{type}_boundary_diff.out" - params: - check_mesh = True, - fields = [ - # second field name can be omitted if identical - ["bulk_node_ids", 0, 0], - ["bulk_element_ids", 0, 0], - ["bulk_face_ids", 0, 0] - ] - wrapper: - f"file://{config['SOURCE_DIR']}/scripts/snakemake/vtkdiff" diff --git a/Applications/Utils/Tests.cmake b/Applications/Utils/Tests.cmake index 2113161ab35..41281936309 100644 --- a/Applications/Utils/Tests.cmake +++ b/Applications/Utils/Tests.cmake @@ -681,21 +681,7 @@ AddTest( ) if(SNAKEMAKE AND TEE_TOOL_PATH) - add_test(NAME snakemake_ExtractBoundary - COMMAND ${SNAKEMAKE} -j 1 - --configfile ${PROJECT_BINARY_DIR}/buildinfo.yaml - -s ${CMAKE_CURRENT_SOURCE_DIR}/ExtractBoundary.smk - ) - - add_test(NAME snakemake_VoxelGridFromLayers - COMMAND ${SNAKEMAKE} -j 1 - --configfile ${PROJECT_BINARY_DIR}/buildinfo.yaml - -s ${CMAKE_CURRENT_SOURCE_DIR}/VoxelGridFromLayers.smk - ) - set_tests_properties(snakemake_ExtractBoundary snakemake_VoxelGridFromLayers - PROPERTIES LABELS "default" - ) - add_dependencies(ctest ExtractBoundary Layers2Grid AddFaultToVoxelGrid generateStructuredMesh) + add_dependencies(ctest Layers2Grid AddFaultToVoxelGrid) endif() AddTest( diff --git a/Tests/Data/FileIO/square_10_1x1_quad_boundary.vtu b/Tests/Data/Utils/ExtractBoundary/square_10_1x1_quad_boundary.vtu similarity index 100% rename from Tests/Data/FileIO/square_10_1x1_quad_boundary.vtu rename to Tests/Data/Utils/ExtractBoundary/square_10_1x1_quad_boundary.vtu diff --git a/Tests/Data/FileIO/square_10_1x1_tri_boundary.vtu b/Tests/Data/Utils/ExtractBoundary/square_10_1x1_tri_boundary.vtu similarity index 100% rename from Tests/Data/FileIO/square_10_1x1_tri_boundary.vtu rename to Tests/Data/Utils/ExtractBoundary/square_10_1x1_tri_boundary.vtu diff --git a/Tests/Data/Utils/ExtractBoundary/test_extract_boundary.py b/Tests/Data/Utils/ExtractBoundary/test_extract_boundary.py new file mode 100644 index 00000000000..9880e46c9a8 --- /dev/null +++ b/Tests/Data/Utils/ExtractBoundary/test_extract_boundary.py @@ -0,0 +1,39 @@ +import os +from pathlib import Path + +import pytest +from ogs import cli + + +@pytest.mark.parametrize(("element_type"), [("tri"), ("quad")]) +def test_extract_boundary(tmp_path, element_type): + os.chdir(Path(__file__).resolve().parent) + mesh_basename = f"square_10_1x1_{element_type}" + mesh_file = Path(f"{tmp_path}/{mesh_basename}.vtu") + cli.generateStructuredMesh( + e=element_type, + lx=1, + ly=1, + nx=10, + ny=10, + o=mesh_file, + ) + assert mesh_file.exists() + + boundary_file = Path(f"{tmp_path}/{mesh_basename}_boundary.vtu") + cli.ExtractBoundary(i=mesh_file, o=boundary_file) + assert boundary_file.exists() + + assert cli.vtkdiff(boundary_file, boundary_file.name, mesh_check=True) == 0 + for field in ["bulk_node_ids", "bulk_element_ids", "bulk_face_ids"]: + assert ( + cli.vtkdiff( + boundary_file, + boundary_file.name, + a=field, + b=field, + abs=0, + rel=0, + ) + == 0 + ) From f8061182cdccb27ecd3974cfd3abc4bef7aebdce Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 24 Jul 2024 15:36:03 +0200 Subject: [PATCH 12/29] [T] Rewritten VoxelGridFromLayers snakemake test to pytest. --- Applications/Utils/Tests.cmake | 28 ++++---- Applications/Utils/VoxelGridFromLayers.smk | 70 ------------------- .../AREHS_2D_AABB_inverted.vtu | 0 .../AREHS_2D_AABB_regular.vtu | 0 .../AREHS_3D_AABB_inverted.vtu | 0 .../AREHS_3D_AABB_regular.vtu | 0 .../VoxelGridFromLayers}/AREHS_Layer0.vtu | 0 .../VoxelGridFromLayers}/AREHS_Layer15.vtu | 0 .../VoxelGridFromLayers}/AREHS_Layer17.vtu | 0 .../VoxelGridFromLayers}/AREHS_Layer9.vtu | 0 .../VoxelGridFromLayers}/AREHS_fault.vtu | 0 .../VoxelGridFromLayers}/AREHS_test.vtu | 0 .../VoxelGridFromLayers}/AREHS_test_fault.vtu | 0 .../VoxelGridFromLayers}/AREHS_test_iso.vtu | 0 .../AREHS_test_layers.txt | 0 .../test_voxelgrid_from_layers.py | 40 +++++++++++ 16 files changed, 52 insertions(+), 86 deletions(-) delete mode 100644 Applications/Utils/VoxelGridFromLayers.smk rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_2D_AABB_inverted.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_2D_AABB_regular.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_3D_AABB_inverted.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_3D_AABB_regular.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_Layer0.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_Layer15.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_Layer17.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_Layer9.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_fault.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_test.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_test_fault.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_test_iso.vtu (100%) rename Tests/Data/{MeshLib => Utils/VoxelGridFromLayers}/AREHS_test_layers.txt (100%) create mode 100644 Tests/Data/Utils/VoxelGridFromLayers/test_voxelgrid_from_layers.py diff --git a/Applications/Utils/Tests.cmake b/Applications/Utils/Tests.cmake index 41281936309..5a109f848d6 100644 --- a/Applications/Utils/Tests.cmake +++ b/Applications/Utils/Tests.cmake @@ -1411,11 +1411,10 @@ endif() AddTest( NAME RemoveMeshElements_AABB_2D_regular - PATH MeshLib - WORKING_DIRECTORY ${Data_SOURCE_DIR}/MeshLib + PATH Utils/VoxelGridFromLayers EXECUTABLE removeMeshElements - EXECUTABLE_ARGS -i AREHS_Layer17.vtu - -o ${Data_BINARY_DIR}/MeshLib/AREHS_2D_AABB_regular.vtu + EXECUTABLE_ARGS -i /AREHS_Layer17.vtu + -o AREHS_2D_AABB_regular.vtu --x-min 12000 --x-max 15000 --y-min 12000 REQUIREMENTS NOT (OGS_USE_MPI) TESTER vtkdiff-mesh @@ -1424,11 +1423,10 @@ AddTest( AddTest( NAME RemoveMeshElements_AABB_2D_inverted - PATH MeshLib - WORKING_DIRECTORY ${Data_SOURCE_DIR}/MeshLib + PATH Utils/VoxelGridFromLayers EXECUTABLE removeMeshElements - EXECUTABLE_ARGS -i AREHS_Layer17.vtu - -o ${Data_BINARY_DIR}/MeshLib/AREHS_2D_AABB_inverted.vtu + EXECUTABLE_ARGS -i /AREHS_Layer17.vtu + -o AREHS_2D_AABB_inverted.vtu --x-min 12000 --x-max 15000 --y-min 12000 --invert REQUIREMENTS NOT (OGS_USE_MPI) TESTER vtkdiff-mesh @@ -1437,11 +1435,10 @@ AddTest( AddTest( NAME RemoveMeshElements_AABB_3D_regular - PATH MeshLib - WORKING_DIRECTORY ${Data_SOURCE_DIR}/MeshLib + PATH Utils/VoxelGridFromLayers EXECUTABLE removeMeshElements - EXECUTABLE_ARGS -i AREHS_test.vtu - -o ${Data_BINARY_DIR}/MeshLib/AREHS_3D_AABB_regular.vtu + EXECUTABLE_ARGS -i /AREHS_test.vtu + -o AREHS_3D_AABB_regular.vtu --x-min 12000 --x-max 15000 --y-min 12000 --z-min -3000 --z-max -2000 REQUIREMENTS NOT (OGS_USE_MPI) TESTER vtkdiff-mesh @@ -1450,11 +1447,10 @@ AddTest( AddTest( NAME RemoveMeshElements_AABB_3D_inverted - PATH MeshLib - WORKING_DIRECTORY ${Data_SOURCE_DIR}/MeshLib + PATH Utils/VoxelGridFromLayers EXECUTABLE removeMeshElements - EXECUTABLE_ARGS -i AREHS_test.vtu - -o ${Data_BINARY_DIR}/MeshLib/AREHS_3D_AABB_inverted.vtu + EXECUTABLE_ARGS -i /AREHS_test.vtu + -o AREHS_3D_AABB_inverted.vtu --x-min 12000 --x-max 15000 --y-min 12000 --z-min -3000 --z-max -2000 --invert REQUIREMENTS NOT (OGS_USE_MPI) TESTER vtkdiff-mesh diff --git a/Applications/Utils/VoxelGridFromLayers.smk b/Applications/Utils/VoxelGridFromLayers.smk deleted file mode 100644 index c67ef318e9d..00000000000 --- a/Applications/Utils/VoxelGridFromLayers.smk +++ /dev/null @@ -1,70 +0,0 @@ -# Usage, e.g.: -# snakemake -s VoxelGridFromLayers.smk -j 1 --configfile $HOME/code/ogs6/build/buildinfo.yaml -# -# buildinfo.yaml contains variables such as Data_BINARY_DIR - -import os -os.environ["PATH"] += os.pathsep + os.pathsep.join([config['BIN_DIR']]) -workdir: f"{config['Data_SOURCE_DIR']}/MeshLib" -out_dir = f"{config['Data_BINARY_DIR']}/MeshLib" - -rule all: - input: - f"{out_dir}/AREHS_test_diff_geometry.out", - f"{out_dir}/AREHS_test_fault_diff.out", - f"{out_dir}/AREHS_test_iso_diff_geometry.out" - -rule layers_to_grid: - input: - "AREHS_test_layers.txt" - output: - f"{out_dir}/AREHS_test.vtu" - shell: - "Layers2Grid -i {input} -o {output} -x 500 -y 300 -z 100" - -rule vtkdiff_grid_geometry: - input: - out = rules.layers_to_grid.output, - ref = "AREHS_test.vtu" - output: - f"{out_dir}/AREHS_test_diff_geometry.out" - shell: - "vtkdiff -m {input.out} {input.ref} 2>&1 | tee {output}" - -rule add_fault_to_grid: - input: - grid = rules.layers_to_grid.output, - fault = "AREHS_fault.vtu" - output: - f"{out_dir}/AREHS_test_fault.vtu" - shell: - "AddFaultToVoxelGrid -i {input.grid} -f {input.fault} -o {output}" - -rule vtkdiff_fault: - input: - a = rules.add_fault_to_grid.output, - b = "AREHS_test_fault.vtu" - output: - f"{out_dir}/AREHS_test_fault_diff.out" - params: - check_mesh = True, - fields = [["MaterialIDs", 0, 0]] - wrapper: - f"file://{config['SOURCE_DIR']}/scripts/snakemake/vtkdiff" - -rule layers_to_grid_iso: - input: - "AREHS_test_layers.txt" - output: - f"{out_dir}/AREHS_test_iso.vtu" - shell: - "Layers2Grid -i {input} -o {output} -x 500" - -rule vtkdiff_grid_iso_geometry: - input: - out = rules.layers_to_grid_iso.output, - ref = "AREHS_test_iso.vtu" - output: - f"{out_dir}/AREHS_test_iso_diff_geometry.out" - shell: - "vtkdiff -m {input.out} {input.ref} 2>&1 | tee {output}" diff --git a/Tests/Data/MeshLib/AREHS_2D_AABB_inverted.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_2D_AABB_inverted.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_2D_AABB_inverted.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_2D_AABB_inverted.vtu diff --git a/Tests/Data/MeshLib/AREHS_2D_AABB_regular.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_2D_AABB_regular.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_2D_AABB_regular.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_2D_AABB_regular.vtu diff --git a/Tests/Data/MeshLib/AREHS_3D_AABB_inverted.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_3D_AABB_inverted.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_3D_AABB_inverted.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_3D_AABB_inverted.vtu diff --git a/Tests/Data/MeshLib/AREHS_3D_AABB_regular.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_3D_AABB_regular.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_3D_AABB_regular.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_3D_AABB_regular.vtu diff --git a/Tests/Data/MeshLib/AREHS_Layer0.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer0.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_Layer0.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer0.vtu diff --git a/Tests/Data/MeshLib/AREHS_Layer15.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer15.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_Layer15.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer15.vtu diff --git a/Tests/Data/MeshLib/AREHS_Layer17.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer17.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_Layer17.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer17.vtu diff --git a/Tests/Data/MeshLib/AREHS_Layer9.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer9.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_Layer9.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_Layer9.vtu diff --git a/Tests/Data/MeshLib/AREHS_fault.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_fault.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_fault.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_fault.vtu diff --git a/Tests/Data/MeshLib/AREHS_test.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_test.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_test.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_test.vtu diff --git a/Tests/Data/MeshLib/AREHS_test_fault.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_fault.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_test_fault.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_fault.vtu diff --git a/Tests/Data/MeshLib/AREHS_test_iso.vtu b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_iso.vtu similarity index 100% rename from Tests/Data/MeshLib/AREHS_test_iso.vtu rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_iso.vtu diff --git a/Tests/Data/MeshLib/AREHS_test_layers.txt b/Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_layers.txt similarity index 100% rename from Tests/Data/MeshLib/AREHS_test_layers.txt rename to Tests/Data/Utils/VoxelGridFromLayers/AREHS_test_layers.txt diff --git a/Tests/Data/Utils/VoxelGridFromLayers/test_voxelgrid_from_layers.py b/Tests/Data/Utils/VoxelGridFromLayers/test_voxelgrid_from_layers.py new file mode 100644 index 00000000000..fb1e52650c1 --- /dev/null +++ b/Tests/Data/Utils/VoxelGridFromLayers/test_voxelgrid_from_layers.py @@ -0,0 +1,40 @@ +import os +from pathlib import Path + +from ogs import cli + + +def test_voxelgrid_from_layers(tmp_path): + os.chdir(Path(__file__).resolve().parent) + + mesh_file = Path(f"{tmp_path}/AREHS_test.vtu") + + cli.Layers2Grid(i="AREHS_test_layers.txt", o=mesh_file, x=500, y=300, z=100) + assert mesh_file.exists() + + assert cli.vtkdiff(mesh_file, "AREHS_test.vtu", mesh_check=None) == 0 + + fault_mesh_file = Path(f"{tmp_path}/AREHS_test_fault.vtu") + cli.AddFaultToVoxelGrid(i=mesh_file, f="AREHS_fault.vtu", o=fault_mesh_file) + assert fault_mesh_file.exists() + + assert cli.vtkdiff(fault_mesh_file, "AREHS_test_fault.vtu", mesh_check=None) == 0 + assert ( + cli.vtkdiff( + fault_mesh_file, + "AREHS_test_fault.vtu", + a="MaterialIDs", + b="MaterialIDs", + abs=0, + rel=0, + ) + == 0 + ) + + # iso + mesh_file = Path(f"{tmp_path}/AREHS_test_iso.vtu") + + cli.Layers2Grid(i="AREHS_test_layers.txt", o=mesh_file, x=500) + assert mesh_file.exists() + + assert cli.vtkdiff(mesh_file, "AREHS_test_iso.vtu", mesh_check=None) == 0 From d8066aae19cae4f41fe04b0603c86d09fd2394ca Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 25 Jul 2024 10:06:14 +0200 Subject: [PATCH 13/29] [T] Rewritten GMSH2OGS_Extractoundary snakemake test to pytest. --- .../Utils/GMSH2OGS_ExtractBoundary.smk | 86 ------------------- .../GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk | 85 ------------------ Applications/Utils/Tests.cmake | 21 ----- .../{MeshLib => Utils/GMSH2OGS}/A2-gmsh.msh | 0 .../{MeshLib => Utils/GMSH2OGS}/A2-gmsh4.msh | 0 Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_0.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_1.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_2.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_3.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_4.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_5.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_6.vtu | 0 .../Data/{MeshLib => Utils/GMSH2OGS}/A2_7.vtu | 0 .../test_gmsh2ogs_extract_boundary.py | 79 +++++++++++++++++ 15 files changed, 79 insertions(+), 192 deletions(-) delete mode 100644 Applications/Utils/GMSH2OGS_ExtractBoundary.smk delete mode 100644 Applications/Utils/GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2-gmsh.msh (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2-gmsh4.msh (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_0.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_1.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_2.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_3.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_4.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_5.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_6.vtu (100%) rename Tests/Data/{MeshLib => Utils/GMSH2OGS}/A2_7.vtu (100%) create mode 100644 Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py diff --git a/Applications/Utils/GMSH2OGS_ExtractBoundary.smk b/Applications/Utils/GMSH2OGS_ExtractBoundary.smk deleted file mode 100644 index fec4376e1c4..00000000000 --- a/Applications/Utils/GMSH2OGS_ExtractBoundary.smk +++ /dev/null @@ -1,86 +0,0 @@ -# Usage, e.g.: -# snakemake -s GMSH2OGS_ExtractBoundary.smk -j 1 --configfile $HOME/code/ogs6/build/buildinfo.yaml -# -# buildinfo.yaml contains variables such as Data_BINARY_DIR - -import os -os.environ["PATH"] += os.pathsep + os.pathsep.join([config['BIN_DIR']]) -workdir: f"{config['Data_BINARY_DIR']}/MeshLib" - -#import ipdb -#ipdb.set_trace() - -VTKDIFF = f"file://{config['SOURCE_DIR']}/scripts/snakemake/vtkdiff" -SOURCE_DIR = f"{config['Data_SOURCE_DIR']}/MeshLib" - -MESH_NAME = "A2" -BULK_MESH = f"{MESH_NAME}.vtu" -GMSH_MESH = f"{MESH_NAME}-gmsh.msh" -GMSH2OGS = f"{config['BIN_DIR']}/GMSH2OGS --gmsh2_physical_id" - -INNER_BOUNDARIES = "[12]" -OUTER_BOUNDARIES = "[034567]" - -ALL_REFERENCE_FILES = glob_wildcards(f"{SOURCE_DIR}/{{file, {MESH_NAME}.*}}.vtu").file - -rule all: - input: - expand("{file}.vtkdiff.out", file=ALL_REFERENCE_FILES) - -rule gmsh2ogs: - input: - f"{SOURCE_DIR}/{GMSH_MESH}" - output: - expand("{file}.vtu", file=ALL_REFERENCE_FILES) - shell: - "{GMSH2OGS} -i {input} -o {BULK_MESH} -e -b -v" - -rule vtkdiff_geometry_bulk: - input: - a = f"{SOURCE_DIR}/{BULK_MESH}", - b = BULK_MESH - output: - f"{MESH_NAME}.vtkdiff.out" - params: - check_mesh = True, - fields = [["MaterialIDs", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_boundary: - input: - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids" - params: - check_mesh = True, - fields = [["bulk_node_ids", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_inner: - input: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids", - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x, {INNER_BOUNDARIES}}}.vtkdiff.out" - params: - check_mesh = True, - fields = [["number_bulk_elements", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_outer: - input: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids", - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x, {OUTER_BOUNDARIES}}}.vtkdiff.out" - params: - check_mesh = True, - fields = [["bulk_element_ids", 0, 0]] - wrapper: - VTKDIFF diff --git a/Applications/Utils/GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk b/Applications/Utils/GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk deleted file mode 100644 index 73d35e5b580..00000000000 --- a/Applications/Utils/GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk +++ /dev/null @@ -1,85 +0,0 @@ -# Usage, e.g.: -# snakemake -s GMSH2OGS_ExtractBoundary.smk -j 1 --configfile $HOME/code/ogs6/build/buildinfo.yaml -# -# buildinfo.yaml contains variables such as Data_BINARY_DIR - -import os -os.environ["PATH"] += os.pathsep + os.pathsep.join([config['BIN_DIR']]) -workdir: f"{config['Data_BINARY_DIR']}/MeshLib" - -#import ipdb -#ipdb.set_trace() - -VTKDIFF = f"file://{config['SOURCE_DIR']}/scripts/snakemake/vtkdiff" -SOURCE_DIR = f"{config['Data_SOURCE_DIR']}/MeshLib" -GMSH2OGS = f"{config['BIN_DIR']}/GMSH2OGS" - -MESH_NAME = "A2" -BULK_MESH = f"{MESH_NAME}.vtu" -GMSH_MESH = f"{MESH_NAME}-gmsh4.msh" -INNER_BOUNDARIES = "[12]" -OUTER_BOUNDARIES = "[034567]" - -ALL_REFERENCE_FILES = glob_wildcards(f"{SOURCE_DIR}/{{file, {MESH_NAME}.*}}.vtu").file - -rule all: - input: - expand("{file}.vtkdiff.out", file=ALL_REFERENCE_FILES) - -rule gmsh2ogs: - input: - f"{SOURCE_DIR}/{GMSH_MESH}" - output: - expand("{file}.vtu", file=ALL_REFERENCE_FILES) - shell: - "{GMSH2OGS} -i {input} -o {BULK_MESH} -e -b -v" - -rule vtkdiff_geometry_bulk: - input: - a = f"{SOURCE_DIR}/{BULK_MESH}", - b = BULK_MESH - output: - f"{MESH_NAME}.vtkdiff.out" - params: - check_mesh = True, - fields = [["MaterialIDs", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_boundary: - input: - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids" - params: - check_mesh = True, - fields = [["bulk_node_ids", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_inner: - input: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids", - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x, {INNER_BOUNDARIES}}}.vtkdiff.out" - params: - check_mesh = True, - fields = [["number_bulk_elements", 0, 0]] - wrapper: - VTKDIFF - -rule vtkdiff_geometry_outer: - input: - f"{MESH_NAME}_{{x}}.vtkdiff.out-bulk_node_ids", - a = f"{SOURCE_DIR}/{MESH_NAME}_{{x}}.vtu", - b = f"{MESH_NAME}_{{x}}.vtu" - output: - f"{MESH_NAME}_{{x, {OUTER_BOUNDARIES}}}.vtkdiff.out" - params: - check_mesh = True, - fields = [["bulk_element_ids", 0, 0]] - wrapper: - VTKDIFF diff --git a/Applications/Utils/Tests.cmake b/Applications/Utils/Tests.cmake index 5a109f848d6..a76ac034d43 100644 --- a/Applications/Utils/Tests.cmake +++ b/Applications/Utils/Tests.cmake @@ -839,27 +839,6 @@ if(TARGET VerticalSliceFromLayers AND GMSH) endif() -if(TARGET GMSH2OGS AND SNAKEMAKE AND TEE_TOOL_PATH) - add_test(NAME snakemake_GMSH2OGS_ExtractBoundary - COMMAND ${SNAKEMAKE} --cores all - --configfile ${PROJECT_BINARY_DIR}/buildinfo.yaml - -s ${CMAKE_CURRENT_SOURCE_DIR}/GMSH2OGS_ExtractBoundary.smk - ) - - add_test(NAME snakemake_GMSH2OGS_Gmsh4_ExtractBoundary - COMMAND ${SNAKEMAKE} --cores all - --configfile ${PROJECT_BINARY_DIR}/buildinfo.yaml - -s ${CMAKE_CURRENT_SOURCE_DIR}/GMSH2OGS_ExtractBoundary_MeshByGmsh4.smk - ) - set_tests_properties( - snakemake_GMSH2OGS_ExtractBoundary - snakemake_GMSH2OGS_Gmsh4_ExtractBoundary - PROPERTIES LABELS "default" RUN_SERIAL TRUE - ) - - add_dependencies(ctest GMSH2OGS) -endif() - foreach(criterion ElementSize EdgeRatio EquiAngleSkew RadiusEdgeRatio SizeDifference) AddTest( NAME TrianglesGoodElementQuality_${criterion}_Test diff --git a/Tests/Data/MeshLib/A2-gmsh.msh b/Tests/Data/Utils/GMSH2OGS/A2-gmsh.msh similarity index 100% rename from Tests/Data/MeshLib/A2-gmsh.msh rename to Tests/Data/Utils/GMSH2OGS/A2-gmsh.msh diff --git a/Tests/Data/MeshLib/A2-gmsh4.msh b/Tests/Data/Utils/GMSH2OGS/A2-gmsh4.msh similarity index 100% rename from Tests/Data/MeshLib/A2-gmsh4.msh rename to Tests/Data/Utils/GMSH2OGS/A2-gmsh4.msh diff --git a/Tests/Data/MeshLib/A2.vtu b/Tests/Data/Utils/GMSH2OGS/A2.vtu similarity index 100% rename from Tests/Data/MeshLib/A2.vtu rename to Tests/Data/Utils/GMSH2OGS/A2.vtu diff --git a/Tests/Data/MeshLib/A2_0.vtu b/Tests/Data/Utils/GMSH2OGS/A2_0.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_0.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_0.vtu diff --git a/Tests/Data/MeshLib/A2_1.vtu b/Tests/Data/Utils/GMSH2OGS/A2_1.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_1.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_1.vtu diff --git a/Tests/Data/MeshLib/A2_2.vtu b/Tests/Data/Utils/GMSH2OGS/A2_2.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_2.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_2.vtu diff --git a/Tests/Data/MeshLib/A2_3.vtu b/Tests/Data/Utils/GMSH2OGS/A2_3.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_3.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_3.vtu diff --git a/Tests/Data/MeshLib/A2_4.vtu b/Tests/Data/Utils/GMSH2OGS/A2_4.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_4.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_4.vtu diff --git a/Tests/Data/MeshLib/A2_5.vtu b/Tests/Data/Utils/GMSH2OGS/A2_5.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_5.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_5.vtu diff --git a/Tests/Data/MeshLib/A2_6.vtu b/Tests/Data/Utils/GMSH2OGS/A2_6.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_6.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_6.vtu diff --git a/Tests/Data/MeshLib/A2_7.vtu b/Tests/Data/Utils/GMSH2OGS/A2_7.vtu similarity index 100% rename from Tests/Data/MeshLib/A2_7.vtu rename to Tests/Data/Utils/GMSH2OGS/A2_7.vtu diff --git a/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py b/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py new file mode 100644 index 00000000000..a3dea98cc2d --- /dev/null +++ b/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py @@ -0,0 +1,79 @@ +import os +from pathlib import Path + +import pytest +from ogs import cli + + +@pytest.mark.parametrize( + ("mesh", "gmsh2_physical_id"), [("A2-gmsh.msh", True), ("A2-gmsh4.msh", False)] +) +def test_gmsh2ogs_extract_boundary(tmp_path, mesh, gmsh2_physical_id): + os.chdir(Path(__file__).resolve().parent) + mesh_file = Path(f"{tmp_path}/A2.vtu") + + cli.GMSH2OGS( + gmsh2_physical_id=gmsh2_physical_id, + i=mesh, + o=mesh_file, + e=True, + boundaries=True, + validation=True, + ) + assert mesh_file.exists() + + # geometry bulk + assert cli.vtkdiff(mesh_file, "A2.vtu", mesh_check=None) == 0 + assert ( + cli.vtkdiff( + mesh_file, + "A2.vtu", + a="MaterialIDs", + b="MaterialIDs", + abs=0, + rel=0, + ) + == 0 + ) + + for x in range(8): + # geometry boundary + assert ( + cli.vtkdiff(f"{tmp_path}/A2_{x}.vtu", f"A2_{x}.vtu", mesh_check=None) == 0 + ) + assert ( + cli.vtkdiff( + f"{tmp_path}/A2_{x}.vtu", + f"A2_{x}.vtu", + a="bulk_node_ids", + b="bulk_node_ids", + abs=0, + rel=0, + ) + == 0 + ) + if x in [1, 2]: # inner boundarie + assert ( + cli.vtkdiff( + f"{tmp_path}/A2_{x}.vtu", + f"A2_{x}.vtu", + a="number_bulk_elements", + b="number_bulk_elements", + abs=0, + rel=0, + ) + == 0 + ) + + if x in [0, 3, 4, 5, 6, 7]: # outer boundarie + assert ( + cli.vtkdiff( + f"{tmp_path}/A2_{x}.vtu", + f"A2_{x}.vtu", + a="bulk_element_ids", + b="bulk_element_ids", + abs=0, + rel=0, + ) + == 0 + ) From 766cbbb03d2e4960f7cd73f9ec0583655701f198 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 25 Jul 2024 14:15:51 +0200 Subject: [PATCH 14/29] [py] Adapted some tests to work in build dir. ogs.simulator works in wheel only --- Tests/Python/test_cli.py | 2 +- Tests/Python/test_matrix_debug_output.py | 21 ++----------------- Tests/Python/test_ogs_asm_threads.py | 21 ++----------------- Tests/Python/test_python_bc_simulation.py | 15 +++---------- Tests/Python/test_simulator.py | 6 +++++- Tests/Python/test_simulator_mesh_interface.py | 6 +++++- 6 files changed, 18 insertions(+), 53 deletions(-) diff --git a/Tests/Python/test_cli.py b/Tests/Python/test_cli.py index 1e13dcb9bc7..8f61c867b9e 100644 --- a/Tests/Python/test_cli.py +++ b/Tests/Python/test_cli.py @@ -6,7 +6,7 @@ def _run(program, args): func = getattr(ogs_cli_wheel, program) - args = ["%s.py" % program] + args + args = [f"{program}.py"] + args with push_argv(args), pytest.raises(SystemExit) as excinfo: func() assert excinfo.value.code == 0 diff --git a/Tests/Python/test_matrix_debug_output.py b/Tests/Python/test_matrix_debug_output.py index 2f4b4436d4a..dad4970179d 100644 --- a/Tests/Python/test_matrix_debug_output.py +++ b/Tests/Python/test_matrix_debug_output.py @@ -3,29 +3,12 @@ import tempfile from pathlib import Path -import ogs.simulator as sim import pytest +from ogs import cli def run(prjpath, outdir, expect_successful): - arguments = ["ogs", prjpath, "-o", outdir] - - try: - while True: - print("Python OpenGeoSys.init ...") - status = sim.initialize(arguments) - - if status != 0: - break - - print("Python OpenGeoSys.executeSimulation ...") - status = sim.executeSimulation() - - break - finally: - print("Python OpenGeoSys.finalize() ...") - sim.finalize() - + status = cli.ogs(prjpath, o=outdir) status_expected = 0 if expect_successful else 1 assert status == status_expected diff --git a/Tests/Python/test_ogs_asm_threads.py b/Tests/Python/test_ogs_asm_threads.py index 73ece7935e2..876b8083698 100644 --- a/Tests/Python/test_ogs_asm_threads.py +++ b/Tests/Python/test_ogs_asm_threads.py @@ -2,29 +2,12 @@ import tempfile from pathlib import Path -import ogs.simulator as sim import pytest +from ogs import cli def run(prjpath, outdir, expect_successful): - arguments = ["ogs", prjpath, "-o", outdir] - - try: - while True: - print("Python OpenGeoSys.init ...") - status = sim.initialize(arguments) - - if status != 0: - break - - print("Python OpenGeoSys.executeSimulation ...") - status = sim.executeSimulation() - - break - finally: - print("Python OpenGeoSys.finalize() ...") - sim.finalize() - + status = cli.ogs(prjpath, o=outdir) status_expected = 0 if expect_successful else 1 assert status == status_expected diff --git a/Tests/Python/test_python_bc_simulation.py b/Tests/Python/test_python_bc_simulation.py index 7ec6bc8a7be..7681dcf587b 100644 --- a/Tests/Python/test_python_bc_simulation.py +++ b/Tests/Python/test_python_bc_simulation.py @@ -1,7 +1,7 @@ import tempfile from pathlib import Path -import ogs.simulator as sim +from ogs import cli def test_HM_ground_equil_TaylorHood_Python(): @@ -12,17 +12,8 @@ def test_HM_ground_equil_TaylorHood_Python(): ) with tempfile.TemporaryDirectory() as tmpdirname: - arguments = ["ogs", str(prjpath), "-o", tmpdirname] - - try: - print("Python OpenGeoSys.init ...") - assert sim.initialize(arguments) == 0 - print("Python OpenGeoSys.executeSimulation ...") - assert sim.executeSimulation() == 0 - finally: - print("Python OpenGeoSys.finalize() ...") - sim.finalize() - + status = cli.ogs(str(prjpath), o=tmpdirname) + assert status == 0 assert ( Path(tmpdirname) / "simHM_ground_quadBCu_python_ts_10_t_1000000.000000.vtu" ).exists() diff --git a/Tests/Python/test_simulator.py b/Tests/Python/test_simulator.py index 0d4ebef4367..7a26ad5afa2 100644 --- a/Tests/Python/test_simulator.py +++ b/Tests/Python/test_simulator.py @@ -1,10 +1,14 @@ +import os import tempfile from pathlib import Path -import ogs.simulator as sim +import pytest +@pytest.mark.skipif("OGS_USE_PATH" in os.environ, reason="Works in wheel only.") def test_simulator(): + import ogs.simulator as sim + current_dir = Path(__file__).parent.resolve() arguments = [ "", diff --git a/Tests/Python/test_simulator_mesh_interface.py b/Tests/Python/test_simulator_mesh_interface.py index 03ae3332f5a..6391c22bdfa 100644 --- a/Tests/Python/test_simulator_mesh_interface.py +++ b/Tests/Python/test_simulator_mesh_interface.py @@ -1,10 +1,11 @@ +import os import sys import tempfile from pathlib import Path import numpy as np import ogs.mesh as mesh # noqa: F401 -from ogs import simulator +import pytest def crossProduct(v, w): @@ -78,7 +79,10 @@ def checkCells(cells, celltypes, points): ) +@pytest.mark.skipif("OGS_USE_PATH" in os.environ, reason="Works in wheel only.") def test_simulator(): + from ogs import simulator + current_dir = Path(__file__).parent.resolve() arguments = [ "", From bf32d2a7dc101f29934446c07779c527cd2e3609 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Fri, 26 Jul 2024 10:37:43 +0200 Subject: [PATCH 15/29] [py] Pass some CMake vars to Python. --- Applications/Python/CMakeLists.txt | 9 +++++++-- Applications/Python/ogs/CMakeLists.txt | 15 +++++++++++++++ Applications/Python/ogs/__init__.py | 12 ++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index 18164c746f2..eedad10786d 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -8,7 +8,7 @@ endif() # wheel: Install into Python module root dir (enables 'import ogs.simulator') set(_py_install_location ogs) if(NOT OGS_BUILD_WHEEL) - set(_py_install_location "{_py_site_packages_dir}/ogs") + set(_py_install_location "${_py_site_packages_dir}/ogs") endif() add_subdirectory(ogs) @@ -41,8 +41,13 @@ if(OGS_USE_PIP) set_tests_properties(pytest PROPERTIES LABELS "default") add_dependencies( - ctest GMSH2OGS Layers2Grid AddFaultToVoxelGrid ExtractBoundary + ctest + GMSH2OGS + Layers2Grid + AddFaultToVoxelGrid + ExtractBoundary vtkdiff + generateStructuredMesh ) endif() diff --git a/Applications/Python/ogs/CMakeLists.txt b/Applications/Python/ogs/CMakeLists.txt index c4b4914fa8a..4bc85db8bab 100644 --- a/Applications/Python/ogs/CMakeLists.txt +++ b/Applications/Python/ogs/CMakeLists.txt @@ -1,3 +1,18 @@ +# cmake-lint: disable=E1126 +set(_config_content + "OGS_USE_PETSC = '@OGS_USE_PETSC@'" "OGS_VERSION = '@OGS_VERSION@'" + "OGS_USE_MKL = '@OGS_USE_MKL@'" +) +string(REPLACE ";" "\n" _config_content "${_config_content}") +set(_config_file ${PROJECT_BINARY_DIR}/site-packages/ogs/config.py) +file(CONFIGURE OUTPUT ${_config_file} CONTENT "${_config_content}") + +if(OGS_BUILD_WHEEL) + install(FILES ${_config_file} DESTINATION ${SKBUILD_PLATLIB_DIR}/ogs) +else() + install(FILES ${_config_file} DESTINATION ${_py_install_location}) +endif() + if(OGS_BUILD_WHEEL) return() endif() diff --git a/Applications/Python/ogs/__init__.py b/Applications/Python/ogs/__init__.py index 7b25c3c8b41..d01cbecd5bf 100644 --- a/Applications/Python/ogs/__init__.py +++ b/Applications/Python/ogs/__init__.py @@ -1 +1,13 @@ +import importlib.util +import os + from ._internal.wrap_cli_tools import cli # noqa: F401 + +if "PEP517_BUILD_BACKEND" in os.environ: + # on wheel build config.py is not generated at the beginning of the build + # but later after CMake has run + config_spec = importlib.util.find_spec(".config", package="ogs") + if config_spec is not None: + from .config import * # noqa: F403 +else: + from .config import * # noqa: F403 From f8270967422bc0caf855f0f704c4e604d5448a72 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Fri, 26 Jul 2024 10:40:48 +0200 Subject: [PATCH 16/29] [py] Some pytest fixes for PETSc config. --- .../aniso_expansion.prj | 17 +++++++++++++---- Tests/Python/test_matrix_debug_output.py | 5 +++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/Tests/Data/ThermoRichardsMechanics/anisotropic_thermal_expansion/aniso_expansion.prj b/Tests/Data/ThermoRichardsMechanics/anisotropic_thermal_expansion/aniso_expansion.prj index 47ce3430c0d..a8810ce04a7 100644 --- a/Tests/Data/ThermoRichardsMechanics/anisotropic_thermal_expansion/aniso_expansion.prj +++ b/Tests/Data/ThermoRichardsMechanics/anisotropic_thermal_expansion/aniso_expansion.prj @@ -37,10 +37,10 @@ Constant 1e-3 - - density - Constant - 1000 + + density + Constant + 1000 specific_heat_capacity @@ -335,6 +335,15 @@ SparseLU + + + -ksp_type bcgs + -pc_type lu + -ksp_rtol 1e-8 + -ksp_atol 1e-12 + -ksp_max_it 4000 + + diff --git a/Tests/Python/test_matrix_debug_output.py b/Tests/Python/test_matrix_debug_output.py index dad4970179d..9a218ecb21d 100644 --- a/Tests/Python/test_matrix_debug_output.py +++ b/Tests/Python/test_matrix_debug_output.py @@ -3,6 +3,7 @@ import tempfile from pathlib import Path +import ogs import pytest from ogs import cli @@ -154,6 +155,10 @@ def test_local_matrix_debug_output(monkeypatch, prefix_parameter, elements_param ("", True, True), # set env var to an empty string ], ) +@pytest.mark.skipif( + ogs.OGS_USE_PETSC == "ON", + reason="global matrix output is not implemented for PETSc matrices", +) def test_global_matrix_debug_output(monkeypatch, prefix_parameter): srcdir = Path(__file__).parent.parent.parent prjpath = srcdir / "Tests/Data/Mechanics/Linear/square_1e2.prj" From 84ae68a76bdf9ac46b58b908a1b7845b660afe3c Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 30 Jul 2024 14:30:08 +0200 Subject: [PATCH 17/29] [py] Fixes for ogs6py interface. --- .../Mechanics/Linear/SimpleMechanics.ipynb | 39 +++++++++---------- .../generateInvalidMediaForHT.py | 32 +++++++-------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb b/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb index 827998d4ee0..01bf6c3f14b 100644 --- a/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb +++ b/Tests/Data/Mechanics/Linear/SimpleMechanics.ipynb @@ -62,7 +62,7 @@ "\n", "prj_name = \"SimpleMechanics\"\n", "model = ogs.OGS(PROJECT_FILE=(out_dir / f\"{prj_name}.prj\"))\n", - "model.geo.add_geom(filename=\"./square_1x1.gml\")\n", + "model.geometry.add_geometry(filename=\"./square_1x1.gml\")\n", "model.mesh.add_mesh(filename=\"./square_1x1_quad_1e2.vtu\")\n", "model.processes.set_process(\n", " name=\"SD\",\n", @@ -76,8 +76,8 @@ "model.processes.add_process_variable(\n", " process_variable=\"process_variable\", process_variable_name=\"displacement\"\n", ")\n", - "model.processes.add_process_variable(secondary_variable=\"sigma\", output_name=\"sigma\")\n", - "model.timeloop.add_process(\n", + "model.processes.add_secondary_variable(internal_name=\"sigma\", output_name=\"sigma\")\n", + "model.time_loop.add_process(\n", " process=\"SD\",\n", " nonlinear_solver_name=\"basic_newton\",\n", " convergence_type=\"DeltaX\",\n", @@ -85,7 +85,7 @@ " abstol=\"1e-15\",\n", " time_discretization=\"BackwardEuler\",\n", ")\n", - "model.timeloop.set_stepping(\n", + "model.time_loop.set_stepping(\n", " process=\"SD\",\n", " type=\"FixedTimeStepping\",\n", " t_initial=\"0\",\n", @@ -93,7 +93,7 @@ " repeat=\"4\",\n", " delta_t=\"0.25\",\n", ")\n", - "model.timeloop.add_output(\n", + "model.time_loop.add_output(\n", " type=\"VTK\",\n", " prefix=prj_name,\n", " repeat=\"1\",\n", @@ -108,13 +108,13 @@ "model.parameters.add_parameter(name=\"displacement0\", type=\"Constant\", values=\"0 0\")\n", "model.parameters.add_parameter(name=\"dirichlet0\", type=\"Constant\", value=\"0\")\n", "model.parameters.add_parameter(name=\"dirichlet1\", type=\"Constant\", value=\"0.05\")\n", - "model.processvars.set_ic(\n", + "model.process_variables.set_ic(\n", " process_variable_name=\"displacement\",\n", " components=\"2\",\n", " order=\"1\",\n", " initial_condition=\"displacement0\",\n", ")\n", - "model.processvars.add_bc(\n", + "model.process_variables.add_bc(\n", " process_variable_name=\"displacement\",\n", " geometrical_set=\"square_1x1_geometry\",\n", " geometry=\"left\",\n", @@ -122,7 +122,7 @@ " component=\"0\",\n", " parameter=\"dirichlet0\",\n", ")\n", - "model.processvars.add_bc(\n", + "model.process_variables.add_bc(\n", " process_variable_name=\"displacement\",\n", " geometrical_set=\"square_1x1_geometry\",\n", " geometry=\"bottom\",\n", @@ -130,7 +130,7 @@ " component=\"1\",\n", " parameter=\"dirichlet0\",\n", ")\n", - "model.processvars.add_bc(\n", + "model.process_variables.add_bc(\n", " process_variable_name=\"displacement\",\n", " geometrical_set=\"square_1x1_geometry\",\n", " geometry=\"top\",\n", @@ -138,13 +138,13 @@ " component=\"1\",\n", " parameter=\"dirichlet1\",\n", ")\n", - "model.nonlinsolvers.add_non_lin_solver(\n", + "model.nonlinear_solvers.add_non_lin_solver(\n", " name=\"basic_newton\",\n", " type=\"Newton\",\n", " max_iter=\"4\",\n", " linear_solver=\"general_linear_solver\",\n", ")\n", - "model.linsolvers.add_lin_solver(\n", + "model.linear_solvers.add_lin_solver(\n", " name=\"general_linear_solver\",\n", " kind=\"lis\",\n", " solver_type=\"cg\",\n", @@ -152,7 +152,7 @@ " max_iteration_step=\"10000\",\n", " error_tolerance=\"1e-16\",\n", ")\n", - "model.linsolvers.add_lin_solver(\n", + "model.linear_solvers.add_lin_solver(\n", " name=\"general_linear_solver\",\n", " kind=\"eigen\",\n", " solver_type=\"CG\",\n", @@ -160,7 +160,7 @@ " max_iteration_step=\"10000\",\n", " error_tolerance=\"1e-16\",\n", ")\n", - "model.linsolvers.add_lin_solver(\n", + "model.linear_solvers.add_lin_solver(\n", " name=\"general_linear_solver\",\n", " kind=\"petsc\",\n", " prefix=\"sd\",\n", @@ -274,9 +274,7 @@ "source": [ "import matplotlib.pyplot as plt\n", "import numpy as np\n", - "\n", "import ogstools as ot\n", - "from ogstools import examples\n", "from ogstools.meshlib import MeshSeries" ] }, @@ -299,15 +297,14 @@ ], "source": [ "mesh_series = MeshSeries(f\"{out_dir}/{prj_name}.pvd\")\n", - "points = np.asarray(\n", - " [[0.3, 0.5, 0.0], [0.24, 0.21, 0.0]]\n", - ")\n", + "points = np.asarray([[0.3, 0.5, 0.0], [0.24, 0.21, 0.0]])\n", "disp = ot.properties.displacement\n", "\n", - "labels = [f\"{i}: {label}\" for i, label in enumerate(ot.plot.utils.justified_labels(points))]\n", + "labels = [\n", + " f\"{i}: {label}\" for i, label in enumerate(ot.plot.utils.justified_labels(points))\n", + "]\n", "fig = mesh_series.plot_probe(\n", - " points=points[:4], mesh_property=disp,\n", - " time_unit=\"a\", labels=labels[:4]\n", + " points=points[:4], mesh_property=disp, time_unit=\"a\", labels=labels[:4]\n", ")" ] }, diff --git a/Tests/Data/Parabolic/HT/InvalidProjectFiles/generateInvalidMediaForHT.py b/Tests/Data/Parabolic/HT/InvalidProjectFiles/generateInvalidMediaForHT.py index 5a9f85a8b5e..8aaa172cfb8 100644 --- a/Tests/Data/Parabolic/HT/InvalidProjectFiles/generateInvalidMediaForHT.py +++ b/Tests/Data/Parabolic/HT/InvalidProjectFiles/generateInvalidMediaForHT.py @@ -137,7 +137,7 @@ def addMediumPropertiesForHT(omit=""): + ".prj" ) model.mesh.add_mesh(filename="square_1x1_quad_1e3.vtu") - model.geo.add_geom(filename="square_1x1.gml") + model.geometry.add_geometry(filename="square_1x1.gml") model.processes.set_process( name="HT", type="HT", integration_order="2", specific_body_force="0 0" ) @@ -147,15 +147,15 @@ def addMediumPropertiesForHT(omit=""): model.processes.add_process_variable( process_variable="pressure", process_variable_name="pressure" ) - model.processes.add_process_variable( - secondary_variable="darcy_velocity", output_name="darcy_velocity" + model.processes.add_secondary_variable( + internal_name="darcy_velocity", output_name="darcy_velocity" ) addAqueousLiquidPropertiesForHT(aqueousfluid_property) addSolidPropertiesForHT(solid_property) addMediumPropertiesForHT(medium_property) - model.timeloop.add_process( + model.time_loop.add_process( process="HT", nonlinear_solver_name="basic_picard", convergence_type="DeltaX", @@ -163,7 +163,7 @@ def addMediumPropertiesForHT(omit=""): abstol="1e-15", time_discretization="BackwardEuler", ) - model.timeloop.set_stepping( + model.time_loop.set_stepping( process="HT", type="FixedTimeStepping", t_initial="0", @@ -171,7 +171,7 @@ def addMediumPropertiesForHT(omit=""): repeat="4", delta_t="0.25", ) - model.timeloop.add_output( + model.time_loop.add_output( type="VTK", prefix="HT_test_", repeat="1", @@ -188,13 +188,13 @@ def addMediumPropertiesForHT(omit=""): name="t_Dirichlet_bottom", type="Constant", value="2" ) # model.parameters.add_parameter(name="t_Dirichlet_top", type="Constant", value="1") - model.processvars.set_ic( + model.process_variables.set_ic( process_variable_name="temperature", components="1", order="1", initial_condition="T0", ) - model.processvars.add_bc( + model.process_variables.add_bc( process_variable_name="temperature", geometrical_set="square_1x1_geometry", geometry="bottom", @@ -202,19 +202,19 @@ def addMediumPropertiesForHT(omit=""): component="0", parameter="t_Dirichlet_bottom", ) - # model.processvars.add_bc(process_variable_name="temperature", + # model.process_variables.add_bc(process_variable_name="temperature", # geometrical_set="square_1x1_geometry", # geometry="top", # type="Dirichlet", # component="1", # parameter="t_Dirichlet_top") - model.processvars.set_ic( + model.process_variables.set_ic( process_variable_name="pressure", components="1", order="1", initial_condition="P0", ) - model.processvars.add_bc( + model.process_variables.add_bc( process_variable_name="pressure", geometrical_set="square_1x1_geometry", geometry="left", @@ -222,19 +222,19 @@ def addMediumPropertiesForHT(omit=""): component="1", parameter="p_Dirichlet_left", ) - # model.processvars.addadd_bcBC(process_variable_name="pressure", + # model.process_variables.addadd_bcBC(process_variable_name="pressure", # geometrical_set="square_1x1_geometry", # geometry="right", # type="Dirichlet", # component="1", # parameter="p_Dirichlet_right") - model.nonlinsolvers.add_non_lin_solver( + model.nonlinear_solvers.add_non_lin_solver( name="basic_picard", type="Picard", max_iter="4", linear_solver="general_linear_solver", ) - model.linsolvers.add_lin_solver( + model.linear_solvers.add_lin_solver( name="general_linear_solver", kind="lis", solver_type="cg", @@ -242,7 +242,7 @@ def addMediumPropertiesForHT(omit=""): max_iteration_step="10000", error_tolerance="1e-16", ) - model.linsolvers.add_lin_solver( + model.linear_solvers.add_lin_solver( name="general_linear_solver", kind="eigen", solver_type="CG", @@ -250,7 +250,7 @@ def addMediumPropertiesForHT(omit=""): max_iteration_step="10000", error_tolerance="1e-16", ) - model.linsolvers.add_lin_solver( + model.linear_solvers.add_lin_solver( name="general_linear_solver", kind="petsc", solver_type="cg", From cc6ab5e7c07af0975635007ee574d2e46aa7a8bd Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 31 Jul 2024 11:58:19 +0200 Subject: [PATCH 18/29] [py] Use a newer triangle on macOS. --- Tests/Data/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Data/requirements.txt b/Tests/Data/requirements.txt index d4b9c54c57f..e5c4eaf49ca 100644 --- a/Tests/Data/requirements.txt +++ b/Tests/Data/requirements.txt @@ -12,3 +12,4 @@ pyvista[all]>=0.40.1 seaborn>=0.12 VTUinterface>=0.704 vtk-osmesa>=9.2.6;platform_system=='Linux' +git+https://github.com/drufat/triangle@5210b64ac5f2aff5673a66938cae56dc0a93a4ff#egg=triangle;platform_system=='Darwin' From 01a0909105dfc6700e4c64b40b809b345623654c Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 31 Jul 2024 12:35:34 +0200 Subject: [PATCH 19/29] [py] Install python modules into spec. dir. in the build folder. Allows co-existance with ogstools python package in build dir virtual environment. Requires to uninstall ogs wheel in venv and to set the PYTHONPATH (both handled by CMake and .envrc-file used by the direnv-tool). --- Applications/Python/CMakeLists.txt | 20 ++++++++------------ CMakeLists.txt | 1 + scripts/cmake/PythonSetup.cmake | 5 +++++ 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index eedad10786d..2a34dbda0f2 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -1,14 +1,11 @@ -set(_py_site_packages_dir - "lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages" -) -if(WIN32) - set(_py_site_packages_dir "Lib/site-packages") -endif() - # wheel: Install into Python module root dir (enables 'import ogs.simulator') set(_py_install_location ogs) +set(_py_build_location ogs) if(NOT OGS_BUILD_WHEEL) - set(_py_install_location "${_py_site_packages_dir}/ogs") + set(_py_install_location + "${CMAKE_INSTALL_LIBDIR}/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages/ogs" + ) + set(_py_build_location "${PROJECT_BINARY_DIR}/site-packages/ogs") endif() add_subdirectory(ogs) @@ -18,13 +15,12 @@ add_subdirectory(ogs.callbacks) if(OGS_USE_PIP) set_target_properties( - simulator mesh callbacks - PROPERTIES LIBRARY_OUTPUT_DIRECTORY - ${LOCAL_VIRTUALENV_DIR}/${_py_site_packages_dir}/ogs + simulator mesh callbacks PROPERTIES LIBRARY_OUTPUT_DIRECTORY + ${_py_build_location} ) file( COPY ogs/. - DESTINATION ${LOCAL_VIRTUALENV_DIR}/${_py_site_packages_dir}/ogs + DESTINATION ${_py_build_location} PATTERN "__pycache__" EXCLUDE PATTERN "CMakeLists.txt" EXCLUDE ) diff --git a/CMakeLists.txt b/CMakeLists.txt index ebebc5510b5..70024bb52b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -238,6 +238,7 @@ set(_envrc_content "[ -d \"${PROJECT_BINARY_DIR}/.venv\" ] && source ${PROJECT_BINARY_DIR}/.venv/bin/activate" "export PATH=$PATH:${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" "export OGS_USE_PATH=1" + "export PYTHONPATH=${PROJECT_BINARY_DIR}/site-packages:$PYTHONPATH" ) if(TFEL_WITH_PYTHON) set(_envrc_content "${_envrc_content}" diff --git a/scripts/cmake/PythonSetup.cmake b/scripts/cmake/PythonSetup.cmake index fb22b42ee2e..96545ddbd91 100644 --- a/scripts/cmake/PythonSetup.cmake +++ b/scripts/cmake/PythonSetup.cmake @@ -175,6 +175,11 @@ function(setup_venv) "To disable pip set OGS_USE_PIP=OFF.\n\n${_out}\n${_err}" ) endif() + # Uninstall ogs wheel + execute_process( + COMMAND ${_apple_env} ${LOCAL_VIRTUALENV_BIN_DIR}/pip uninstall + --yes ogs WORKING_DIRECTORY ${PROJECT_BINARY_DIR} + ) endif() endfunction() From 188f44d6dcfbfe95afae02b651143c513b1ec951 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Mon, 5 Aug 2024 10:44:10 +0200 Subject: [PATCH 20/29] [nb] Format notebooks. --- ...Linear_Disc_with_hole_convergence_analysis.ipynb | 13 ++++++++++--- .../Kregime_Propagating_jupyter.ipynb | 7 +------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb b/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb index 0415bdf182a..4c873db83e1 100644 --- a/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb +++ b/Tests/Data/Mechanics/Linear/DiscWithHole/Linear_Disc_with_hole_convergence_analysis.ipynb @@ -639,8 +639,12 @@ } ], "source": [ - "domain_8 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_8/disc_with_hole_idx_is_8_domain.vtu\")\n", - "domain_80 = pv.read(f\"{out_dir}/disc_with_hole_idx_is_80/disc_with_hole_idx_is_80_domain.vtu\")\n", + "domain_8 = pv.read(\n", + " f\"{out_dir}/disc_with_hole_idx_is_8/disc_with_hole_idx_is_8_domain.vtu\"\n", + ")\n", + "domain_80 = pv.read(\n", + " f\"{out_dir}/disc_with_hole_idx_is_80/disc_with_hole_idx_is_80_domain.vtu\"\n", + ")\n", "\n", "p = pv.Plotter(shape=(1, 2), border=False)\n", "p.subplot(0, 0)\n", @@ -727,7 +731,10 @@ " prj_path = out_dir / prj_file\n", "\n", " model = ogs.OGS(INPUT_FILE=prj_path, PROJECT_FILE=prj_path)\n", - " model.run_model(logfile=f\"{out_dir}/out.txt\", args=f\"-o {out_dir} -m {out_dir}/disc_with_hole_idx_is_{idx}\")" + " model.run_model(\n", + " logfile=f\"{out_dir}/out.txt\",\n", + " args=f\"-o {out_dir} -m {out_dir}/disc_with_hole_idx_is_{idx}\",\n", + " )" ] }, { diff --git a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb index d7cf2909b51..d376a7ef7ba 100644 --- a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb +++ b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb @@ -363,12 +363,7 @@ " mesh_generation(0.1, h)\n", " # Convert GMSH (.msh) meshes to VTU meshes appropriate for OGS simulation.\n", " input_file = f\"{out_dir}/\" + meshname + \".msh\"\n", - " msh2vtu(\n", - " filename=input_file,\n", - " output_path=out_dir,\n", - " reindex=True,\n", - " keep_ids=True\n", - " )\n", + " msh2vtu(filename=input_file, output_path=out_dir, reindex=True, keep_ids=True)\n", " %cd {out_dir}\n", " ! identifySubdomains -f -m mesh_full_pf_domain.vtu -- mesh_full_pf_physical_group_*.vtu\n", " %cd -\n", From 9784ba8e85ff0c21d2686a15178cf1960fded9ab Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Mon, 5 Aug 2024 10:46:39 +0200 Subject: [PATCH 21/29] [py] Ruff auto-fixes. --- .pre-commit-config.yaml | 4 ++-- .../MFront/ModCamClay_ShearTest.py | 22 +++++++++---------- .../SeabedResponse/Stationary_waves.ipynb | 8 +++---- .../Linear/PythonHertzContact/post.py | 4 ++-- .../Kregime_Propagating_jupyter.ipynb | 1 - .../Kregime_Static_jupyter.ipynb | 12 +++++----- .../surfing_pyvista.ipynb | 4 ++-- 7 files changed, 26 insertions(+), 29 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4a4e2b3c215..35d1d5e6435 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -80,7 +80,7 @@ repos: - id: vale args: [--output=line, --minAlertLevel=error] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.2" + rev: "v0.5.0" hooks: - id: ruff types_or: [python, pyi, jupyter] @@ -90,7 +90,7 @@ repos: # Run this hook (and all other manual hooks if any) with: # pre-commit run --hook-stage manual - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.4.2" + rev: "v0.5.0" hooks: - id: ruff types_or: [python, pyi, jupyter] diff --git a/MaterialLib/SolidModels/MFront/ModCamClay_ShearTest.py b/MaterialLib/SolidModels/MFront/ModCamClay_ShearTest.py index c97d9db8e18..fd328879308 100644 --- a/MaterialLib/SolidModels/MFront/ModCamClay_ShearTest.py +++ b/MaterialLib/SolidModels/MFront/ModCamClay_ShearTest.py @@ -143,7 +143,7 @@ ax.set_title("Total volume/solid volume over time") for k in range(runs): ax.plot( - ltime, results[2][k], label=prelabel + "%.2f" % (valueList[k]) + ltime, results[2][k], label=prelabel + f"{valueList[k]:.2f}" ) # OCR: pc0/valueList[k] ax.set_xlabel("$t$ / s") ax.set_ylabel("volume ratio") @@ -155,7 +155,7 @@ fig, ax = plt.subplots() ax.set_title("Porosity over time") for k in range(runs): - ax.plot(ltime, results[3][k], label=prelabel + "%.2f" % (valueList[k])) + ax.plot(ltime, results[3][k], label=prelabel + f"{valueList[k]:.2f}") ax.set_xlabel("$t$ / s") ax.set_ylabel(r"$\phi$") ax.grid() @@ -165,7 +165,7 @@ fig, ax = plt.subplots() # ax.set_title('Shear stress over shear strain') for k in range(runs): - ax.plot(results[4][k], results[5][k], label=prelabel + "%.2f" % (valueList[k])) + ax.plot(results[4][k], results[5][k], label=prelabel + f"{valueList[k]:.2f}") ax.set_xlabel(r"$\epsilon_{xy}$") ax.set_ylabel(r"$\sigma_{xy}$ / MPa") ax.grid() @@ -175,9 +175,7 @@ fig, ax = plt.subplots() # ax.set_title('Plastic volumetric strain over shear strain') for k in range(runs): - ax.plot( - results[4][k], results[7][k] * 100, label=prelabel + "%.2f" % (valueList[k]) - ) + ax.plot(results[4][k], results[7][k] * 100, label=prelabel + f"{valueList[k]:.2f}") ax.set_xlabel(r"$\epsilon_{xy}$") ax.set_ylabel(r"${\epsilon}_p^V$ / %") ax.grid() @@ -187,11 +185,11 @@ fig, ax = plt.subplots() ax.set_title("Hydrostatic pressure and von-Mises stress over time") for k in range(runs): - ax.plot(ltime, results[0][k], label=prelabel + "%.2f" % (valueList[k])) + ax.plot(ltime, results[0][k], label=prelabel + f"{valueList[k]:.2f}") ax.plot( ltime, results[1][k], - label=prelabel + "%.2f" % (valueList[k]), + label=prelabel + f"{valueList[k]:.2f}", linestyle="dashed", ) ax.set_xlabel("$t$ / s") @@ -205,10 +203,10 @@ ax.plot( ltime, results[1][k], - label=prelabel + "%.2f" % (valueList[k]), + label=prelabel + f"{valueList[k]:.2f}", linestyle="dashed", ) - ax.plot(ltime, results[6][k], label=prelabel + "%.2f" % (valueList[k])) + ax.plot(ltime, results[6][k], label=prelabel + f"{valueList[k]:.2f}") ax.set_xlabel("$t$ / s") ax.set_ylabel("$p, p_c$ / MPa") ax.grid() @@ -221,9 +219,9 @@ ax.plot(pRange, M * pRange, color="black", label="CSL") for k in range(runs): # final yield surface - ax.scatter(pRangeFinal[k], qFunctFinal[k], label=prelabel + "%.2f" % (valueList[k])) + ax.scatter(pRangeFinal[k], qFunctFinal[k], label=prelabel + f"{valueList[k]:.2f}") # stress trajectory - ax.plot(results[1][k], results[0][k], label=prelabel + "%.2f" % (valueList[k])) + ax.plot(results[1][k], results[0][k], label=prelabel + f"{valueList[k]:.2f}") ax.set_xlabel("$p$ / MPa") ax.set_ylabel("$q$ / MPa") ax.grid() diff --git a/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb b/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb index 6b545dde586..23ec8088474 100644 --- a/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb +++ b/Tests/Data/HydroMechanics/SeabedResponse/Stationary_waves.ipynb @@ -341,7 +341,7 @@ " compute_pressure_and_stresses(t, 0, y)[0],\n", " -y_rel,\n", " color=colors[t],\n", - " label=\"t = %.1f s\" % t,\n", + " label=f\"t = {t:.1f} s\",\n", " )\n", "\n", "t = 2.5\n", @@ -1082,7 +1082,7 @@ " compute_pressure_and_stresses(t, x, y)[0],\n", " -y_rel,\n", " color=colors[t],\n", - " label=\"analytical, t = %.1f s\" % t,\n", + " label=f\"analytical, t = {t:.1f} s\",\n", " )\n", "\n", "ax[1][0].plot(\n", @@ -1125,12 +1125,12 @@ " \"o\",\n", " markevery=10,\n", " color=colors[t_num],\n", - " label=\"numerical, t = %.1f s\" % t_num,\n", + " label=f\"numerical, t = {t_num:.1f} s\",\n", " )\n", " ax[0][0].set_xlabel(\"$p$ / $\\\\tilde{p}$\")\n", "\n", " ax[0][1].plot(\n", - " f_abs_pressure, depth / 100, color=colors[t_num], label=\"t = %.1f s\" % t_num\n", + " f_abs_pressure, depth / 100, color=colors[t_num], label=f\"t = {t_num:.1f} s\"\n", " )\n", " ax[0][1].set_xlabel(\"$\\\\Delta p /\\\\tilde{p}$\")\n", "\n", diff --git a/Tests/Data/Mechanics/Linear/PythonHertzContact/post.py b/Tests/Data/Mechanics/Linear/PythonHertzContact/post.py index c4bba3cbd6a..6d24a97d3ef 100755 --- a/Tests/Data/Mechanics/Linear/PythonHertzContact/post.py +++ b/Tests/Data/Mechanics/Linear/PythonHertzContact/post.py @@ -177,7 +177,7 @@ def average_stress(rs, stress): except: print(max(xis), r_contact) raise - avg_stress[i] = 1.0 / rho_max * np.trapz(x=rhos, y=stress_int(xis)) + avg_stress[i] = 1.0 / rho_max * np.trapezoid(x=rhos, y=stress_int(xis)) # avg_stress[-1] = 0.0 return rs_int, avg_stress @@ -187,7 +187,7 @@ def total_force(rs, stress): rs_int = np.linspace(min(rs), max(rs), max(len(rs), 200)) stress_int = interp1d(rs, stress, bounds_error=False, fill_value=0.0) - return 2.0 * np.pi * np.trapz(x=rs_int, y=rs_int * stress_int(rs_int)) + return 2.0 * np.pi * np.trapezoid(x=rs_int, y=rs_int * stress_int(rs_int)) if t > 0: plane.SetOrigin(0, y_at_r_contact, 0) diff --git a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb index d376a7ef7ba..14f9651f5b2 100644 --- a/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb +++ b/Tests/Data/PhaseField/Kregime_Propagating_jupyter_notebook/Kregime_Propagating_jupyter.ipynb @@ -133,7 +133,6 @@ }, "outputs": [], "source": [ - "import argparse\n", "import math\n", "import os\n", "import re\n", diff --git a/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb b/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb index a79093c6081..f6374abafe7 100644 --- a/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb +++ b/Tests/Data/PhaseField/kregime_jupyter_notebook/Kregime_Static_jupyter.ipynb @@ -303,7 +303,7 @@ " # mesh properties\n", " ls = 2 * h\n", " # generate prefix from properties\n", - " filename = \"results_h_%0.4f\" % h\n", + " filename = f\"results_h_{h:0.4f}\"\n", " mesh_generation(0.1, h)\n", " # Convert GMSH (.msh) meshes to VTU meshes appropriate for OGS simulation.\n", " input_file = f\"{out_dir}/\" + meshname + \".msh\" # noqa: F841\n", @@ -429,7 +429,7 @@ " slice_mesh = mesh.slice(normal=normal, origin=point)\n", " y_slice = slice_mesh.points[:, 1]\n", " Wnode_slice = slice_mesh.point_data[\"Wnode\"]\n", - " width_i = np.trapz(Wnode_slice, x=y_slice)\n", + " width_i = np.trapz(Wnode_slice, x=y_slice) # noqa: NPY201\n", " if width_i >= 0:\n", " width_line[i] = width_i\n", " r_i[i] = (\n", @@ -507,7 +507,7 @@ "for j, h_j in enumerate(h_list):\n", " r_i_num = []\n", " width_line_num = []\n", - " filename = \"results_h_%0.4f\" % h_j\n", + " filename = f\"results_h_{h_j:0.4f}\"\n", " print(filename)\n", " width_calculation(filename)\n", " r_i_num = width_calculation(filename)[0]\n", @@ -524,7 +524,7 @@ " fillstyle=\"none\",\n", " markersize=0,\n", " linewidth=lineWIDTH[0],\n", - " label=\"Closed form solution - $h= $%0.4f\" % h_j,\n", + " label=f\"Closed form solution - $h= ${h_j:0.4f}\",\n", " )\n", " plt.plot(\n", " np.array(r_i_num[:]),\n", @@ -533,7 +533,7 @@ " fillstyle=\"none\",\n", " markersize=6,\n", " linewidth=lineWIDTH[1],\n", - " label=\"VPF - $h =$%0.4f\" % h_j,\n", + " label=f\"VPF - $h =${h_j:0.4f}\",\n", " )\n", " # ------------------------------------------------------------------------\n", "plt.rcParams[\"figure.figsize\"] = [40, 20]\n", @@ -541,7 +541,7 @@ "plt.ylabel(\"$w_n$ [m]\", fontsize=14)\n", "plt.xlabel(\"$r$ [m]\", fontsize=14)\n", "plt.grid(linestyle=\"dashed\")\n", - "plt.title(\"%s\" % phasefield_model)\n", + "plt.title(f\"{phasefield_model}\")\n", "\n", "legend = plt.legend(bbox_to_anchor=(1.04, 1), loc=\"upper left\")\n", "plt.show()" diff --git a/Tests/Data/PhaseField/surfing_jupyter_notebook/surfing_pyvista.ipynb b/Tests/Data/PhaseField/surfing_jupyter_notebook/surfing_pyvista.ipynb index a3ca95f9575..63066739bb3 100644 --- a/Tests/Data/PhaseField/surfing_jupyter_notebook/surfing_pyvista.ipynb +++ b/Tests/Data/PhaseField/surfing_jupyter_notebook/surfing_pyvista.ipynb @@ -633,7 +633,7 @@ " \"-ob\",\n", " fillstyle=\"none\",\n", " linewidth=1.5,\n", - " label=\"Phase-field %s\" % phasefield_model,\n", + " label=f\"Phase-field {phasefield_model}\",\n", ")\n", "plt.plot(\n", " G_theta_time[:, 0],\n", @@ -659,7 +659,7 @@ " \"-ob\",\n", " fillstyle=\"none\",\n", " linewidth=1.5,\n", - " label=\"Phase-field %s\" % phasefield_model,\n", + " label=f\"Phase-field {phasefield_model}\",\n", ")\n", "plt.grid(linestyle=\"dashed\")\n", "plt.xlim(-0.05, 0.8)\n", From 2a23de4090856505a9d11d26f244e5810ccd1461 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 6 Aug 2024 11:25:07 +0200 Subject: [PATCH 22/29] [ogs6py] Use patch for preventing empty -tags. --- Tests/Data/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Tests/Data/requirements.txt b/Tests/Data/requirements.txt index e5c4eaf49ca..136079915d7 100644 --- a/Tests/Data/requirements.txt +++ b/Tests/Data/requirements.txt @@ -1,5 +1,6 @@ --extra-index-url https://gitlab.kitware.com/api/v4/projects/13/packages/pypi/simple git+https://gitlab.opengeosys.org/ogs/tools/ogstools@b4f3780274c464260ff43a248fac7379e49c8975#egg=ogstools +git+https://github.com/bilke/ogs6py@66410a2acc6db77f33c78949e0601670895b0af6#egg=ogs6py gmsh>=4.11 h5py>=3.8 git+https://github.com/joergbuchwald/heatsource_thm@bbd5bab17fc2ec228c773e087dc847e1ad5f9a4c#egg=heatsource-py From 2fb0d64e668c6d0069b63dd27b4f358b2151a040 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 6 Aug 2024 13:07:33 +0200 Subject: [PATCH 23/29] [py] .envrc.ps1 for Windows. --- CMakeLists.txt | 33 ++++++++++++------- Tests/Python/test_simulator_mesh_interface.py | 11 ++++++- scripts/ci/extends/template-build-win.yml | 3 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70024bb52b7..77be929a127 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -234,19 +234,30 @@ if(OGS_WRITE_BENCHMARK_COMMANDS) endif() # cmake-lint: disable=E1126 -set(_envrc_content - "[ -d \"${PROJECT_BINARY_DIR}/.venv\" ] && source ${PROJECT_BINARY_DIR}/.venv/bin/activate" - "export PATH=$PATH:${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" - "export OGS_USE_PATH=1" - "export PYTHONPATH=${PROJECT_BINARY_DIR}/site-packages:$PYTHONPATH" -) -if(TFEL_WITH_PYTHON) - set(_envrc_content "${_envrc_content}" - "export PYTHONPATH=${TFEL_WITH_PYTHON}:$PYTHONPATH" +if(WIN32) + set(_envrc_file_ending ".ps1") + set(_envrc_content + "$Env:PYTHONPATH += \";${PROJECT_BINARY_DIR}/site-packages\"" + "$Env:PATH += \";${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}\"" + "$Env:PATH += \";C:/Program Files (x86)/Intel/oneAPI/compiler/latest/windows/redist/intel64_win/compiler\"" + "$Env:OGS_USE_PATH = \"1\"" + ) + string(REPLACE ";$" "\n$" _envrc_content "${_envrc_content}") +else() + set(_envrc_content + "[ -d \"${PROJECT_BINARY_DIR}/.venv\" ] && source ${PROJECT_BINARY_DIR}/.venv/bin/activate" + "export PATH=$PATH:${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}" + "export OGS_USE_PATH=1" + "export PYTHONPATH=${PROJECT_BINARY_DIR}/site-packages:$PYTHONPATH" ) + if(TFEL_WITH_PYTHON) + set(_envrc_content "${_envrc_content}" + "export PYTHONPATH=${TFEL_WITH_PYTHON}:$PYTHONPATH" + ) + endif() + string(REPLACE ";" "\n" _envrc_content "${_envrc_content}") endif() -string(REPLACE ";" "\n" _envrc_content "${_envrc_content}") -file(CONFIGURE OUTPUT .envrc CONTENT "${_envrc_content}") +file(CONFIGURE OUTPUT .envrc${_envrc_file_ending} CONTENT "${_envrc_content}") check_header_compilation() diff --git a/Tests/Python/test_simulator_mesh_interface.py b/Tests/Python/test_simulator_mesh_interface.py index 6391c22bdfa..6fa509bdcab 100644 --- a/Tests/Python/test_simulator_mesh_interface.py +++ b/Tests/Python/test_simulator_mesh_interface.py @@ -1,10 +1,11 @@ import os +import platform import sys import tempfile from pathlib import Path import numpy as np -import ogs.mesh as mesh # noqa: F401 +import ogs import pytest @@ -81,6 +82,14 @@ def checkCells(cells, celltypes, points): @pytest.mark.skipif("OGS_USE_PATH" in os.environ, reason="Works in wheel only.") def test_simulator(): + if platform.system() == "Windows" and ogs.OGS_USE_MKL == "ON": + os.add_dll_directory( + Path( + "C:/Program Files (x86)/Intel/oneAPI/compiler/latest/windows/redist/intel64_win/compiler" + ) + ) + + import ogs.mesh as mesh # noqa: F401 from ogs import simulator current_dir = Path(__file__).parent.resolve() diff --git a/scripts/ci/extends/template-build-win.yml b/scripts/ci/extends/template-build-win.yml index e9d1fe363f8..467f8170773 100644 --- a/scripts/ci/extends/template-build-win.yml +++ b/scripts/ci/extends/template-build-win.yml @@ -12,7 +12,7 @@ - $log_file = $build_directory_full + "\make.txt" - (rm -r -fo $build_directory_full) - cmd /c if not exist $build_directory_full mkdir $build_directory_full - - mkdir build # We are inside the OGS source directory, now. This "build" dir will be, too. + - mkdir build # We are inside the OGS source directory, now. This "build" dir will be, too. # Create symlink https://stackoverflow.com/a/34905638/80480 - cmd /c mklink /D $artifacts_dir $env:CI_PROJECT_DIR\$build_directory_full - $cmake_cmd = "cmake --preset=$env:CMAKE_PRESET --log-level=VERBOSE -Wno-dev $env:CMAKE_ARGS" @@ -23,6 +23,7 @@ if (Test-Path $build_directory_full\.venv\Scripts\Activate.ps1) { Invoke-Expression $build_directory_full\.venv\Scripts\Activate.ps1 } + - Invoke-Expression $build_directory_full\.envrc.ps1 - cmake --build --preset=$env:CMAKE_PRESET --target package | Tee-Object -FilePath $log_file - if($env:BUILD_TESTS -eq "true") { cmake --build --preset=$env:CMAKE_PRESET --target tests } - $ctest_group = "Experimental" From 0cc67e8371946319bae9506acf0d4d6639925547 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 7 Aug 2024 10:42:37 +0200 Subject: [PATCH 24/29] [U] Use double quotes in mpmetis call. --- .../Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp b/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp index bf4017eaa78..8556e31d777 100644 --- a/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp +++ b/Applications/Utils/ModelPreparation/PartitionMesh/PartitionMesh.cpp @@ -198,8 +198,8 @@ int main(int argc, char* argv[]) INFO("Path to mpmetis is: \n\t{:s}", exe_path); const std::string mpmetis_com = - BaseLib::joinPaths(exe_path, "mpmetis") + " -gtype=nodal " + "'" + - metis_mesh + ".mesh" + "' " + std::to_string(nparts.getValue()); + BaseLib::joinPaths(exe_path, "mpmetis") + " -gtype=nodal " + "\"" + + metis_mesh + ".mesh" + "\" " + std::to_string(nparts.getValue()); INFO("Running: {:s}", mpmetis_com); const int status = system(mpmetis_com.c_str()); From 08e4cf5ac0715e4ee1d0bbc4ec63d0d06f7623ec Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Wed, 7 Aug 2024 14:53:58 +0200 Subject: [PATCH 25/29] [T] Add ctest label python. --- Applications/Python/CMakeLists.txt | 4 +++- scripts/cmake/test/NotebookTest.cmake | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index 2a34dbda0f2..8611240e997 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -34,7 +34,9 @@ if(OGS_USE_PIP) COMMAND pytest -c ${PROJECT_SOURCE_DIR}/pyproject.toml WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} ) - set_tests_properties(pytest PROPERTIES LABELS "default") + set_tests_properties( + pytest PROPERTIES LABELS "default;python" COST 10 + ) add_dependencies( ctest diff --git a/scripts/cmake/test/NotebookTest.cmake b/scripts/cmake/test/NotebookTest.cmake index 82e6d914751..a56e0560188 100644 --- a/scripts/cmake/test/NotebookTest.cmake +++ b/scripts/cmake/test/NotebookTest.cmake @@ -46,7 +46,7 @@ function(NotebookTest) if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/ProcessLib) current_dir_as_list(ProcessLib labels) endif() - list(APPEND labels Notebook) + list(APPEND labels Notebook python) if(DEFINED NotebookTest_LABELS) list(APPEND labels ${NotebookTest_LABELS}) else() From cfa16f4fe818a962034023ce448ee3ff81e830f9 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Thu, 8 Aug 2024 10:09:38 +0200 Subject: [PATCH 26/29] [py] pytest uses AddTestWrapper to write log files. --- Applications/Python/CMakeLists.txt | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Applications/Python/CMakeLists.txt b/Applications/Python/CMakeLists.txt index 8611240e997..6d0f1171608 100644 --- a/Applications/Python/CMakeLists.txt +++ b/Applications/Python/CMakeLists.txt @@ -28,11 +28,17 @@ if(OGS_USE_PIP) if(NOT ENABLE_ASAN) add_test( NAME pytest - # TODO: currently failing with: - # - # Can't add new modules after the interpreter has been initialized - COMMAND pytest -c ${PROJECT_SOURCE_DIR}/pyproject.toml - WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMAND + ${CMAKE_COMMAND} -DEXECUTABLE=pytest + "-DEXECUTABLE_ARGS=-c;${PROJECT_SOURCE_DIR}/pyproject.toml" # Quoted + # because + # passed as list see https://stackoverflow.com/a/33248574/80480 + -DBINARY_PATH=${_binary_path} + -DWORKING_DIRECTORY=${PROJECT_SOURCE_DIR} + "-DLOG_ROOT=${PROJECT_BINARY_DIR}/logs" + "-DLOG_FILE_BASENAME=pytest.txt" + "-DTEST_COMMAND_IS_EXPECTED_TO_SUCCEED=TRUE" -P + ${PROJECT_SOURCE_DIR}/scripts/cmake/test/AddTestWrapper.cmake ) set_tests_properties( pytest PROPERTIES LABELS "default;python" COST 10 From 81e418a462c720fa71f12226826c3c2e440377b2 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 13 Aug 2024 06:56:21 +0000 Subject: [PATCH 27/29] Apply 4 suggestion(s) to 2 file(s) Co-authored-by: Christoph Lehmann --- Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py | 4 ++-- web/content/docs/devguide/advanced/python-wheel/index.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py b/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py index a3dea98cc2d..88c78b72c3a 100644 --- a/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py +++ b/Tests/Data/Utils/GMSH2OGS/test_gmsh2ogs_extract_boundary.py @@ -52,7 +52,7 @@ def test_gmsh2ogs_extract_boundary(tmp_path, mesh, gmsh2_physical_id): ) == 0 ) - if x in [1, 2]: # inner boundarie + if x in [1, 2]: # inner boundaries assert ( cli.vtkdiff( f"{tmp_path}/A2_{x}.vtu", @@ -65,7 +65,7 @@ def test_gmsh2ogs_extract_boundary(tmp_path, mesh, gmsh2_physical_id): == 0 ) - if x in [0, 3, 4, 5, 6, 7]: # outer boundarie + if x in [0, 3, 4, 5, 6, 7]: # outer boundaries assert ( cli.vtkdiff( f"{tmp_path}/A2_{x}.vtu", diff --git a/web/content/docs/devguide/advanced/python-wheel/index.md b/web/content/docs/devguide/advanced/python-wheel/index.md index f67bca8b9b9..ca6f351dd68 100644 --- a/web/content/docs/devguide/advanced/python-wheel/index.md +++ b/web/content/docs/devguide/advanced/python-wheel/index.md @@ -21,12 +21,12 @@ There are two ways to build OGS with Python bindings: To run the Python-based tests: -- Source `build-dir/.envrc` (activates the virtual environment and sets `OGS_USE_PATH` environment variable) +- Source `build-dir/.envrc` (i.e., run `source build-dir/.envrc` in your terminal. This activates the virtual environment and sets `OGS_USE_PATH` environment variable). - Run e.g. `pytest` from inside the source directory. On Windows run `Invoke-Expression build-dir/.envrc.ps1` in your PowerShell. - Run e.g. `pytest` from inside the source directory or `pytest ../path/to/source/dir`. - Alternatively you can also run the Python-based with `ctest`, e.g. `ctest -R pytest`. -If you make modifications on the C++ side you need to run `make` or `ninja` in the build directory again. If you make modifications on the Python bindings you need to run `cmake .` again in the build directory. Modifications on the Python tests are immediately available to `pytest`. +If you make modifications on the C++ side you need to run `make` or `ninja` in the build directory again. If you modify Python code you need to run `cmake .` again in the build directory. Modifications on the Python tests are immediately available to `pytest`. To get the output of a specific test: From f561d24034572e263e417d488bf4565f707731d5 Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 13 Aug 2024 10:13:36 +0200 Subject: [PATCH 28/29] [py] Fix OGS_USE_PATH debug output. --- .../Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py b/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py index 24707ff7bd6..de6e2c4a06c 100644 --- a/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py +++ b/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py @@ -119,7 +119,7 @@ def _program(name, args): exe = OGS_BIN_DIR / name if OGS_USE_PATH: exe = name - print(f"OGS_USE_PATH is true: {name} from $PATH is used!") + print(f"OGS_USE_PATH is true: {name} from $PATH is used!") return subprocess.run([exe] + args).returncode # noqa: PLW1510 FUNC_TEMPLATE = """def {0}(): raise SystemExit(_program("{0}", sys.argv[1:]))""" From 4e9d1924cbaa67d78ff002ab12321e8e4e1288df Mon Sep 17 00:00:00 2001 From: Lars Bilke Date: Tue, 13 Aug 2024 15:14:49 +0200 Subject: [PATCH 29/29] [py] Fix OGS_BIN_DIR. --- .../ogs/_internal/provide_ogs_cli_tools_via_wheel.py | 10 ++++++---- Applications/Python/ogs/_internal/wrap_cli_tools.py | 4 +++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py b/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py index de6e2c4a06c..e6de6c64909 100644 --- a/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py +++ b/Applications/Python/ogs/_internal/provide_ogs_cli_tools_via_wheel.py @@ -6,10 +6,6 @@ from . import OGS_USE_PATH -# Here, we assume that this script is installed, e.g., in a virtual environment -# alongside a "bin" directory. -OGS_BIN_DIR = Path(__file__).parent.parent.parent / "bin" - binaries_list = [ "addDataToRaster", "AddElementQuality", @@ -112,6 +108,12 @@ def ogs_with_args(argv): if "PEP517_BUILD_BACKEND" not in os.environ: + # Here, we assume that this script is installed, e.g., in a virtual environment + # alongside a "bin" directory. + OGS_BIN_DIR = Path(__file__).parent.parent.parent / "bin" # installed wheel + if not OGS_BIN_DIR.exists(): + OGS_BIN_DIR = OGS_BIN_DIR.parent # build directory + if platform.system() == "Windows": os.add_dll_directory(OGS_BIN_DIR) diff --git a/Applications/Python/ogs/_internal/wrap_cli_tools.py b/Applications/Python/ogs/_internal/wrap_cli_tools.py index c571b025d1a..98cd7d53de6 100644 --- a/Applications/Python/ogs/_internal/wrap_cli_tools.py +++ b/Applications/Python/ogs/_internal/wrap_cli_tools.py @@ -6,7 +6,9 @@ # Here, we assume that this script is installed, e.g., in a virtual environment # alongside a "bin" directory. -OGS_BIN_DIR = Path(__file__).parent.parent.parent / "bin" +OGS_BIN_DIR = Path(__file__).parent.parent.parent / "bin" # installed wheel +if not OGS_BIN_DIR.exists(): + OGS_BIN_DIR = OGS_BIN_DIR.parent # build directory class CLI: