mmgpy 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mmgpy might be problematic. Click here for more details.

@@ -0,0 +1,39 @@
1
+ name: Build and Test
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request: # Any pull request
7
+ workflow_dispatch: # Allow manual triggering of the workflow
8
+ schedule:
9
+ - cron: "0 0 * * *" # Run at midnight UTC every day
10
+
11
+ jobs:
12
+ build-and-test:
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ os:
17
+ - ubuntu-latest
18
+ - windows-latest
19
+ - macos-latest
20
+ python-version:
21
+ - "3.10"
22
+ - "3.13"
23
+
24
+ runs-on: ${{ matrix.os }}
25
+
26
+ steps:
27
+ - uses: actions/checkout@v4
28
+ - uses: astral-sh/setup-uv@v4
29
+ with:
30
+ python-version: ${{ matrix.python-version }}
31
+
32
+ - run: uv sync
33
+
34
+ - if: runner.os == 'Windows'
35
+ run: .\.venv\Scripts\mmg3d.exe -in tests/Mesh.mesh -out tests/output_exe.mesh
36
+ - if: runner.os != 'Windows'
37
+ run: .venv/bin/mmg3d -in tests/Mesh.mesh -out tests/output_exe.mesh
38
+
39
+ - run: uv run pytest
@@ -0,0 +1,33 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ strategy:
11
+ matrix:
12
+ os: [ubuntu-latest, windows-latest, macos-latest]
13
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
14
+
15
+ runs-on: ${{ matrix.os }}
16
+
17
+ permissions:
18
+ id-token: write
19
+
20
+ steps:
21
+ - uses: actions/checkout@v4
22
+
23
+ - uses: astral-sh/setup-uv@v4
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Build package
28
+ run: uv build --no-sources
29
+
30
+ - name: Publish to PyPI
31
+ env:
32
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
33
+ run: uv publish
mmgpy-0.1.0/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,76 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+
3
+ # Set CMP0177 policy
4
+ if(POLICY CMP0177)
5
+ cmake_policy(SET CMP0177 NEW)
6
+ endif()
7
+
8
+ project(mmgpy VERSION 0.1.0)
9
+
10
+ # Find Python first
11
+ find_package(Python COMPONENTS Interpreter Development REQUIRED)
12
+
13
+ # Try to find system pybind11
14
+ find_package(pybind11 QUIET)
15
+
16
+ # If pybind11 was not found, try to find it via Python
17
+ if(NOT pybind11_FOUND)
18
+ message(STATUS "pybind11 not found in system, trying to locate it via Python...")
19
+
20
+ # Execute Python to find pybind11
21
+ execute_process(
22
+ COMMAND "${Python_EXECUTABLE}" -c "import pybind11; print(pybind11.get_cmake_dir())"
23
+ OUTPUT_VARIABLE PYBIND11_CMAKE_DIR
24
+ OUTPUT_STRIP_TRAILING_WHITESPACE
25
+ RESULT_VARIABLE PYBIND11_RESULT
26
+ )
27
+
28
+ if(PYBIND11_RESULT EQUAL 0)
29
+ message(STATUS "Found pybind11 via Python at: ${PYBIND11_CMAKE_DIR}")
30
+ list(APPEND CMAKE_PREFIX_PATH "${PYBIND11_CMAKE_DIR}")
31
+ find_package(pybind11 REQUIRED)
32
+ else()
33
+ message(FATAL_ERROR "Could not find pybind11. Please install it with: pip install pybind11")
34
+ endif()
35
+ endif()
36
+
37
+ set(CMAKE_CXX_STANDARD 17)
38
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
39
+ set(CMAKE_CXX_EXTENSIONS OFF)
40
+
41
+ # Build external dependencies (MMG)
42
+ add_subdirectory(extern)
43
+
44
+ # Add project source
45
+ add_subdirectory(src)
46
+
47
+ # Enable testing
48
+ option(BUILD_TESTING "Build tests" ON)
49
+ if(BUILD_TESTING)
50
+ enable_testing()
51
+ add_subdirectory(tests)
52
+ endif()
53
+
54
+ # Installation settings
55
+ include(GNUInstallDirs)
56
+
57
+ # Install the Python package
58
+ install(
59
+ DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/src/mmgpy/"
60
+ DESTINATION "${Python_SITEARCH}/mmgpy"
61
+ FILES_MATCHING PATTERN "*.py"
62
+ )
63
+
64
+ # Install the compiled extension
65
+ install(
66
+ TARGETS mmgpy
67
+ LIBRARY DESTINATION "${Python_SITEARCH}/mmgpy"
68
+ )
69
+
70
+ # Print status
71
+ message(STATUS "")
72
+ message(STATUS "MMGpy configuration summary:")
73
+ message(STATUS " Python executable: ${Python_EXECUTABLE}")
74
+ message(STATUS " Python version: ${Python_VERSION}")
75
+ message(STATUS " Install path: ${Python_SITEARCH}/mmgpy")
76
+ message(STATUS "")
mmgpy-0.1.0/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ # Project License
2
+
3
+ This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0+).
4
+
5
+ ## Dependencies
6
+
7
+ mmg (https://www.mmgtools.org/)
8
+
9
+ - Licensed under GNU Lesser General Public License v3.0 or later (LGPL-3.0+)
10
+ - Copyright (c) Bx INP/Inria/UBordeaux/UPMC, 2004-
11
+
12
+ Full license texts can be found in:
13
+
14
+ - COPYING: GNU General Public License v3.0
15
+ - COPYING.LESSER: GNU Lesser General Public License v3.0
16
+
17
+ This project is distributed in the hope that it will be useful, but WITHOUT ANY
18
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
19
+ PARTICULAR PURPOSE. See the GNU General Public License for more details.
mmgpy-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.1
2
+ Name: mmgpy
3
+ Version: 0.1.0
4
+ Summary: Python bindings for the MMG software
5
+ Requires-Python: >=3.10
6
+ Description-Content-Type: text/markdown
7
+
8
+ # mmgpy
9
+
10
+ This is a Python package that provides bindings for the [MMG software](https://www.mmgtools.org) for mesh generation and optimization.
11
+
12
+ ## Installation
13
+
14
+ To install the package, run the following command:
15
+
16
+ ```bash
17
+ pip install mmgpy
18
+ ```
19
+
20
+ Or directly from this repository:
21
+
22
+ ```bash
23
+ pip install git+https://github.com/kmarchais/mmgpy.git
24
+ ```
25
+
26
+ for `uv` users:
27
+
28
+ ```bash
29
+ uv pip install mmgpy
30
+ ```
31
+
32
+ ## Build dependencies
33
+
34
+ - pybind11: Used for Python bindings
35
+
36
+ - BSD 3-Clause License
37
+ - Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
38
+
39
+ - CMake (>= 3.0): Build system
40
+
41
+ - BSD 3-Clause License
42
+ - Copyright 2000-2024 Kitware, Inc. and Contributors
43
+
44
+ - scikit-build: Python build system integration
45
+
46
+ - MIT License
47
+ - Copyright (c) 2014 Mike Sarahan
48
+
49
+ - pytest: Testing framework
50
+
51
+ - MIT License
52
+ - Copyright (c) 2004 Holger Krekel and others
mmgpy-0.1.0/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # mmgpy
2
+
3
+ This is a Python package that provides bindings for the [MMG software](https://www.mmgtools.org) for mesh generation and optimization.
4
+
5
+ ## Installation
6
+
7
+ To install the package, run the following command:
8
+
9
+ ```bash
10
+ pip install mmgpy
11
+ ```
12
+
13
+ Or directly from this repository:
14
+
15
+ ```bash
16
+ pip install git+https://github.com/kmarchais/mmgpy.git
17
+ ```
18
+
19
+ for `uv` users:
20
+
21
+ ```bash
22
+ uv pip install mmgpy
23
+ ```
24
+
25
+ ## Build dependencies
26
+
27
+ - pybind11: Used for Python bindings
28
+
29
+ - BSD 3-Clause License
30
+ - Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
31
+
32
+ - CMake (>= 3.0): Build system
33
+
34
+ - BSD 3-Clause License
35
+ - Copyright 2000-2024 Kitware, Inc. and Contributors
36
+
37
+ - scikit-build: Python build system integration
38
+
39
+ - MIT License
40
+ - Copyright (c) 2014 Mike Sarahan
41
+
42
+ - pytest: Testing framework
43
+
44
+ - MIT License
45
+ - Copyright (c) 2004 Holger Krekel and others
@@ -0,0 +1,53 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+
3
+ include(FetchContent)
4
+
5
+ # Set MMG version
6
+ set(MMG_GIT_TAG "v5.8.0" CACHE STRING "MMG version to build")
7
+ set(MMG_REPOSITORY "https://github.com/MmgTools/mmg.git" CACHE STRING "MMG repository URL")
8
+
9
+ # Fetch MMG
10
+ FetchContent_Declare(
11
+ mmg
12
+ GIT_REPOSITORY ${MMG_REPOSITORY}
13
+ GIT_TAG ${MMG_GIT_TAG}
14
+ )
15
+
16
+ # Configure MMG build options before making it available
17
+ set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries" FORCE)
18
+ set(BUILD_TESTING OFF CACHE BOOL "Disable MMG testing" FORCE)
19
+ set(BUILD_MMG ON CACHE BOOL "Build all MMG libraries" FORCE)
20
+ set(BUILD_MMG2D ON CACHE BOOL "Build MMG2D library" FORCE)
21
+ set(BUILD_MMG3D ON CACHE BOOL "Build MMG3D library" FORCE)
22
+ set(BUILD_MMGS ON CACHE BOOL "Build MMGS library" FORCE)
23
+ set(LIBMMG2D_SHARED ON CACHE BOOL "Build MMG2D shared library" FORCE)
24
+ set(LIBMMG3D_SHARED ON CACHE BOOL "Build MMG3D shared library" FORCE)
25
+ set(LIBMMGS_SHARED ON CACHE BOOL "Build MMGS shared library" FORCE)
26
+ set(LIBMMG2D_STATIC OFF CACHE BOOL "Do not build static libraries" FORCE)
27
+ set(LIBMMG3D_STATIC OFF CACHE BOOL "Do not build static libraries" FORCE)
28
+ set(LIBMMGS_STATIC OFF CACHE BOOL "Do not build static libraries" FORCE)
29
+
30
+ # Make MMG available
31
+ FetchContent_MakeAvailable(mmg)
32
+
33
+ # Set the correct library targets
34
+ set(MMG_LIBRARIES
35
+ libmmg2d_so
36
+ libmmg3d_so
37
+ libmmgs_so
38
+ CACHE INTERNAL ""
39
+ )
40
+
41
+ # Export MMG include directories
42
+ set(MMG_INCLUDE_DIRS
43
+ ${mmg_SOURCE_DIR}/src/common
44
+ ${mmg_SOURCE_DIR}/src/mmg2d
45
+ ${mmg_SOURCE_DIR}/src/mmg3d
46
+ ${mmg_SOURCE_DIR}/src/mmgs
47
+ ${mmg_BINARY_DIR}/src/common
48
+ ${mmg_BINARY_DIR}/include/mmg/common
49
+ ${mmg_BINARY_DIR}/include/mmg/mmg2d
50
+ ${mmg_BINARY_DIR}/include/mmg/mmg3d
51
+ ${mmg_BINARY_DIR}/include/mmg/mmgs
52
+ CACHE INTERNAL ""
53
+ )
@@ -0,0 +1,24 @@
1
+ [build-system]
2
+ requires = ["scikit-build-core>=0.8.0", "pybind11"]
3
+ build-backend = "scikit_build_core.build"
4
+
5
+ [project]
6
+ name = "mmgpy"
7
+ version = "0.1.0"
8
+ description = "Python bindings for the MMG software"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ dependencies = []
12
+
13
+ [tool.scikit-build]
14
+ build.verbose = true
15
+ cmake.version = ">=3.15"
16
+ sdist.include = ["CMakeLists.txt", "src/*", "extern/*"]
17
+ wheel.packages = ["src/mmgpy"]
18
+
19
+ [tool.scikit-build.cmake.define]
20
+ BUILD_TESTING = "OFF"
21
+ BUILD_SHARED_LIBS = "ON"
22
+
23
+ [dependency-groups]
24
+ dev = ["pytest>=8.3.4"]
@@ -0,0 +1,123 @@
1
+ cmake_minimum_required(VERSION 3.15)
2
+ # Create the core binding module
3
+ pybind11_add_module(mmgpy
4
+ bindings/mmgs.cpp
5
+ bindings/mmg3d.cpp
6
+ bindings/mmg2d.cpp
7
+ bindings/bindings.cpp
8
+ )
9
+ # Set include directories
10
+ target_include_directories(mmgpy
11
+ PRIVATE
12
+ ${MMG_INCLUDE_DIRS}
13
+ ${mmg_BINARY_DIR}/include
14
+ ${mmg_SOURCE_DIR}/include
15
+ )
16
+ # Link against MMG libraries
17
+ target_link_libraries(mmgpy
18
+ PRIVATE
19
+ ${MMG_LIBRARIES}
20
+ )
21
+ # Handle compiler warnings
22
+ if(MSVC)
23
+ target_compile_options(mmgpy PRIVATE /W4)
24
+ else()
25
+ target_compile_options(mmgpy PRIVATE -Wall -Wextra -Wpedantic)
26
+ endif()
27
+ # Set the output name
28
+ set_target_properties(mmgpy PROPERTIES
29
+ OUTPUT_NAME "_mmgpy"
30
+ PREFIX ""
31
+ SUFFIX "${PYTHON_MODULE_EXTENSION}"
32
+ )
33
+
34
+ if(UNIX)
35
+ # Set RPATH settings
36
+ set_target_properties(mmgpy PROPERTIES
37
+ INSTALL_RPATH "$ORIGIN"
38
+ BUILD_WITH_INSTALL_RPATH TRUE
39
+ SKIP_BUILD_RPATH FALSE
40
+ )
41
+ endif()
42
+
43
+ # Install the Python module
44
+ install(TARGETS mmgpy DESTINATION mmgpy)
45
+
46
+ if(WIN32)
47
+ # Windows-specific installation
48
+ if(CMAKE_BUILD_TYPE)
49
+ set(MMG_EXE_DIR "${mmg_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}")
50
+ else()
51
+ set(MMG_EXE_DIR "${mmg_BINARY_DIR}/bin/Release")
52
+ endif()
53
+
54
+ install(TARGETS libmmg2d_so libmmg3d_so libmmgs_so
55
+ DESTINATION mmgpy)
56
+ install(TARGETS libmmg2d_so libmmg3d_so libmmgs_so
57
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}")
58
+ install(FILES
59
+ "${MMG_EXE_DIR}/mmg2d.exe"
60
+ "${MMG_EXE_DIR}/mmg3d.exe"
61
+ "${MMG_EXE_DIR}/mmgs.exe"
62
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}"
63
+ )
64
+ else()
65
+ # Set RPATH settings for Python module
66
+ set_target_properties(mmgpy PROPERTIES
67
+ INSTALL_RPATH "$ORIGIN"
68
+ BUILD_WITH_INSTALL_RPATH TRUE
69
+ SKIP_BUILD_RPATH FALSE
70
+ )
71
+
72
+ # Install libraries
73
+ install(TARGETS libmmg2d_so libmmg3d_so libmmgs_so
74
+ DESTINATION mmgpy)
75
+ install(TARGETS libmmg2d_so libmmg3d_so libmmgs_so
76
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}")
77
+
78
+ # Install executables with RPATH set
79
+ install(FILES
80
+ "${mmg_BINARY_DIR}/bin/mmg2d_O3"
81
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}"
82
+ RENAME "mmg2d"
83
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
84
+ GROUP_READ GROUP_EXECUTE
85
+ WORLD_READ WORLD_EXECUTE
86
+ )
87
+ install(CODE "
88
+ execute_process(
89
+ COMMAND patchelf --set-rpath \"$ORIGIN\"
90
+ \"\${CMAKE_INSTALL_PREFIX}/${SKBUILD_SCRIPTS_DIR}/mmg2d\"
91
+ )
92
+ ")
93
+
94
+ install(FILES
95
+ "${mmg_BINARY_DIR}/bin/mmg3d_O3"
96
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}"
97
+ RENAME "mmg3d"
98
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
99
+ GROUP_READ GROUP_EXECUTE
100
+ WORLD_READ WORLD_EXECUTE
101
+ )
102
+ install(CODE "
103
+ execute_process(
104
+ COMMAND patchelf --set-rpath \"$ORIGIN\"
105
+ \"\${CMAKE_INSTALL_PREFIX}/${SKBUILD_SCRIPTS_DIR}/mmg3d\"
106
+ )
107
+ ")
108
+
109
+ install(FILES
110
+ "${mmg_BINARY_DIR}/bin/mmgs_O3"
111
+ DESTINATION "${SKBUILD_SCRIPTS_DIR}"
112
+ RENAME "mmgs"
113
+ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
114
+ GROUP_READ GROUP_EXECUTE
115
+ WORLD_READ WORLD_EXECUTE
116
+ )
117
+ install(CODE "
118
+ execute_process(
119
+ COMMAND patchelf --set-rpath \"$ORIGIN\"
120
+ \"\${CMAKE_INSTALL_PREFIX}/${SKBUILD_SCRIPTS_DIR}/mmgs\"
121
+ )
122
+ ")
123
+ endif()
@@ -0,0 +1,34 @@
1
+ #include "bindings.h"
2
+
3
+ #include "mmg/common/mmgversion.h"
4
+
5
+ #include <pybind11/pybind11.h>
6
+ #include <pybind11/stl.h>
7
+
8
+ PYBIND11_MODULE(_mmgpy, m) {
9
+ py::class_<mmg3d>(m, "mmg3d")
10
+ .def_static("remesh", remesh_3d,
11
+ py::arg("input_mesh"),
12
+ py::arg("input_sol") = "",
13
+ py::arg("output_mesh") = "output.mesh",
14
+ py::arg("output_sol") = "",
15
+ py::arg("options") = py::dict());
16
+
17
+ py::class_<mmg2d>(m, "mmg2d")
18
+ .def_static("remesh", remesh_2d,
19
+ py::arg("input_mesh"),
20
+ py::arg("input_sol") = "",
21
+ py::arg("output_mesh") = "output.mesh",
22
+ py::arg("output_sol") = "",
23
+ py::arg("options") = py::dict());
24
+
25
+ py::class_<mmgs>(m, "mmgs")
26
+ .def_static("remesh", remesh_s,
27
+ py::arg("input_mesh"),
28
+ py::arg("input_sol") = "",
29
+ py::arg("output_mesh") = "output.mesh",
30
+ py::arg("output_sol") = "",
31
+ py::arg("options") = py::dict());
32
+
33
+ m.attr("MMG_VERSION") = MMG_VERSION_RELEASE;
34
+ }
@@ -0,0 +1,18 @@
1
+ #pragma once
2
+
3
+ #include <string>
4
+
5
+ #include <pybind11/pybind11.h>
6
+ #include <pybind11/stl.h>
7
+
8
+ namespace py = pybind11;
9
+
10
+ class mmg3d {};
11
+ class mmg2d {};
12
+ class mmgs {};
13
+
14
+ bool remesh_2d(const std::string& input_mesh, const std::string& input_sol, const std::string& output_mesh, const std::string& output_sol, py::dict options);
15
+
16
+ bool remesh_3d(const std::string& input_mesh, const std::string& input_sol, const std::string& output_mesh, const std::string& output_sol, py::dict options);
17
+
18
+ bool remesh_s(const std::string& input_mesh, const std::string& input_sol, const std::string& output_mesh, const std::string& output_sol, py::dict options);
@@ -0,0 +1,135 @@
1
+ #include <pybind11/pybind11.h>
2
+ #include <pybind11/stl.h>
3
+ #include "mmg/mmg2d/libmmg2d.h"
4
+ #include "mmg_common.hpp"
5
+ #include "bindings.h"
6
+
7
+
8
+ namespace py = pybind11;
9
+
10
+ // Helper function to initialize MMG2D structures
11
+ std::tuple<MMG5_pMesh, MMG5_pSol, MMG5_pSol, MMG5_pSol> init_mmg2d_structures() {
12
+ MMG5_pMesh mesh = nullptr;
13
+ MMG5_pSol met = nullptr, disp = nullptr, ls = nullptr;
14
+
15
+ MMG2D_Init_mesh(MMG5_ARG_start,
16
+ MMG5_ARG_ppMesh, &mesh,
17
+ MMG5_ARG_ppMet, &met,
18
+ MMG5_ARG_ppLs, &ls,
19
+ MMG5_ARG_ppDisp, &disp,
20
+ MMG5_ARG_end);
21
+
22
+ return std::make_tuple(mesh, met, disp, ls);
23
+ }
24
+
25
+ // Helper function to cleanup MMG2D structures
26
+ void cleanup_mmg2d_structures(MMG5_pMesh& mesh, MMG5_pSol& met, MMG5_pSol& disp, MMG5_pSol& ls) {
27
+ MMG2D_Free_all(MMG5_ARG_start,
28
+ MMG5_ARG_ppMesh, &mesh,
29
+ MMG5_ARG_ppMet, &met,
30
+ MMG5_ARG_ppDisp, &disp,
31
+ MMG5_ARG_ppLs, &ls,
32
+ MMG5_ARG_end);
33
+ }
34
+
35
+ // Helper function to load mesh based on format
36
+ int mmg2d_load_mesh(MMG5_pMesh mesh, MMG5_pSol met, MMG5_pSol sol, const std::string& filename) {
37
+ std::string ext = get_file_extension(filename);
38
+ if (ext == ".vtk") {
39
+ return MMG2D_loadVtkMesh(mesh, met, sol, filename.c_str());
40
+ } else if (ext == ".vtu") {
41
+ return MMG2D_loadVtuMesh(mesh, met, sol, filename.c_str());
42
+ } else if (ext == ".vtp") {
43
+ return MMG2D_loadVtpMesh(mesh, met, sol, filename.c_str());
44
+ } else {
45
+ return MMG2D_loadMesh(mesh, filename.c_str());
46
+ }
47
+ }
48
+
49
+ // Helper function to save mesh based on format
50
+ int mmg2d_save_mesh(MMG5_pMesh mesh, MMG5_pSol met, const std::string& filename) {
51
+ std::string ext = get_file_extension(filename);
52
+ if (ext == ".vtk") {
53
+ return MMG2D_saveVtkMesh(mesh, met, filename.c_str());
54
+ } else if (ext == ".vtu") {
55
+ return MMG2D_saveVtuMesh(mesh, met, filename.c_str());
56
+ } else if (ext == ".vtp") {
57
+ return MMG2D_saveVtpMesh(mesh, met, filename.c_str());
58
+ } else {
59
+ return MMG2D_saveMesh(mesh, filename.c_str());
60
+ }
61
+ }
62
+
63
+ bool remesh_2d(const std::string& input_mesh, const std::string& input_sol,
64
+ const std::string& output_mesh, const std::string& output_sol,
65
+ py::dict options) {
66
+ // Initialize structures
67
+ auto [mesh, met, disp, ls] = init_mmg2d_structures();
68
+
69
+ // Set mesh names
70
+ MMG2D_Set_inputMeshName(mesh, input_mesh.c_str());
71
+ MMG2D_Set_outputMeshName(mesh, output_mesh.c_str());
72
+
73
+ if (!input_sol.empty()) {
74
+ MMG2D_Set_inputSolName(mesh, met, input_sol.c_str());
75
+ }
76
+ if (!output_sol.empty()) {
77
+ MMG2D_Set_outputSolName(mesh, met, output_sol.c_str());
78
+ }
79
+
80
+ try {
81
+ // Load mesh
82
+ if (mmg2d_load_mesh(mesh, met,
83
+ (mesh->info.iso || mesh->info.isosurf) ? ls : met,
84
+ input_mesh) != 1) {
85
+ throw std::runtime_error("Failed to load input mesh");
86
+ }
87
+
88
+ // Load solution if provided
89
+ if (!input_sol.empty()) {
90
+ if (MMG2D_loadSol(mesh, met, input_sol.c_str()) != 1) {
91
+ throw std::runtime_error("Failed to load solution file");
92
+ }
93
+ }
94
+
95
+ // Set all mesh options
96
+ set_mesh_options(mesh, met, options);
97
+
98
+ // Process mesh based on mode
99
+ int ret;
100
+ if (mesh->info.lag > -1) {
101
+ ret = MMG2D_mmg2dmov(mesh, met, disp);
102
+ } else if (mesh->info.iso || mesh->info.isosurf) {
103
+ ret = MMG2D_mmg2dls(mesh, ls, met);
104
+ } else if (!mesh->nt) {
105
+ // Mesh generation mode (no triangles in input mesh)
106
+ ret = MMG2D_mmg2dmesh(mesh, met);
107
+ } else {
108
+ // Standard remeshing mode
109
+ ret = MMG2D_mmg2dlib(mesh, met);
110
+ }
111
+
112
+ if (ret != MMG5_SUCCESS) {
113
+ throw std::runtime_error("Remeshing failed");
114
+ }
115
+
116
+ // Save mesh
117
+ if (mmg2d_save_mesh(mesh, met, output_mesh) != 1) {
118
+ throw std::runtime_error("Failed to save output mesh");
119
+ }
120
+
121
+ // Save solution if requested
122
+ if (!output_sol.empty()) {
123
+ if (MMG2D_saveSol(mesh, met, output_sol.c_str()) != 1) {
124
+ throw std::runtime_error("Failed to save output solution");
125
+ }
126
+ }
127
+
128
+ cleanup_mmg2d_structures(mesh, met, disp, ls);
129
+ return true;
130
+
131
+ } catch (const std::exception& e) {
132
+ cleanup_mmg2d_structures(mesh, met, disp, ls);
133
+ throw;
134
+ }
135
+ }