Metadata-Version: 2.2
Name: meshdic
Version: 0.1.0
Summary: C++ implementation of Mesh-DIC with Python bindings
Author: LeeBDa
License: MIT License
         
         Copyright (c) 2026 LeeBDa
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
         
Requires-Python: >=3.10
Requires-Dist: numpy>=1.21
Requires-Dist: pyyaml>=6.0
Requires-Dist: opencv-python>=4.5
Requires-Dist: scipy>=1.7
Provides-Extra: mesh
Requires-Dist: pygmsh>=7.0; extra == "mesh"
Requires-Dist: gmsh; extra == "mesh"
Requires-Dist: meshio; extra == "mesh"
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-benchmark; extra == "dev"
Description-Content-Type: text/markdown

# MeshDIC

MeshDIC is a Python package for 2D finite-element global digital image
correlation (FE-Global DIC). The high-cost numerical routines are implemented
in C++ and exposed to Python with pybind11.

The implementation follows the optimization flow of `2D_FE_Global_DIC-main`.

## Features

- T3, Q4, and Q8 finite elements.
- Project-owned nodal initialization using local 6-parameter affine ICGN.
- Global solver selectable by configuration:
  - `forward_gn`: forward-additive Gauss-Newton; Hessian and residual are
    rebuilt every iteration from deformed-image gradients at warped positions.
  - `icgn`: fixed-Hessian forward-additive mode using reference-image gradients.
- Backtracking line search for global updates.
- Fifth-order B-spline image interpolation.
- Automatic mesh generation from an ROI mask, plus external mesh import through
  `meshio`.
- Pixel displacement fields generated by FE isoparametric shape-function
  interpolation inside each element.
- Green-Lagrange strain estimates at mesh nodes.

## Repository Layout

```text
MeshDIC/
|-- src/
|   |-- mesh_dic/          # Python API, mesh generation, orchestration
|   `-- cpp/               # C++ DIC core and pybind11 bindings
|-- config/
|   `-- default.yaml       # Solver and mesh defaults
|-- case/
|   |-- ring/              # Example images and ROI
|   `-- star/              # Example images and ROI
|-- tests/
|   |-- test_dic.py        # Smoke/unit tests
|   `-- run_cases.py       # Run bundled cases
`-- visualize_results.py   # Standalone visualization runner
```

Generated case outputs are written under `case/<case>/result/<element>/`.
Generated meshes are written under `case/<case>/mesh/`. Both are ignored by
Git.

## Installation

Requirements:

- Python 3.10+
- CMake 3.15+
- A C++17 compiler
- Visual Studio C++ Build Tools on Windows

Install in editable mode:

```powershell
python -m pip install -e .
```

This builds the `mesh_dic._core` extension. Re-run the same command after
changing files under `src/cpp/`.

Optional mesh-generation dependencies are installed with:

```powershell
python -m pip install -e ".[mesh]"
```

## Quick Start

```python
from mesh_dic import solve

result = solve(
    ref_image="case/ring/001.bmp",
    def_image="case/ring/002.bmp",
    roi_mask="case/ring/003.bmp",
    mesh_dir="case/ring/mesh",
    mesh_size=30.0,
    element_type="Q8",
    method="forward_gn",
    alpha=0.01,
    max_iter=30,
    tol=1e-3,
)
```

Important result fields:

- `U`: nodal displacement, shape `(n_nodes, 2)`.
- `U_init`: initial nodal displacement from local affine ICGN.
- `U_pixel`, `V_pixel`: full-field pixel displacements interpolated from FE
  nodal values with element shape functions.
- `field_mask`: valid pixels covered by the FE element mapping.
- `nodes`: nodal coordinates.
- `elements`: one-based element connectivity.
- `Exx`, `Eyy`, `Exy`: nodal Green-Lagrange strain components.
- `iterations`: global solver iterations.
- `method`: normalized global solver method name.

## Configuration

Default settings live in `config/default.yaml`.

```yaml
solver:
  alpha: 0.1
  init_nodal: true
  init_subpixel: true
  init_subset_radius: 20
  init_search_radius: 15
  init_local_max_iter: 50
  init_local_tol: 1.0e-6
  init_local_lambda: 1.0e-6
  method: "forward_gn"
  max_iter: 10
  tol: 0.001

images:
  ref: ""
  def: ""
  roi: ""

mesh:
  dir: "./mesh/"
  size: 30.0
  element_type: "Q8"
  external_file: ""
```

Key parameters:

- `solver.method`: `forward_gn` for full forward Gauss-Newton, or `icgn` for
  the fixed-Hessian mode.
- `solver.alpha`: displacement-gradient regularization weight. Large values
  can over-smooth the displacement field.
- `solver.init_*`: local affine ICGN settings used to initialize nodal
  displacements.
- `mesh.element_type`: `T3`, `Q4`, or `Q8`.
- `mesh.external_file`: optional external mesh file; when set, automatic mesh
  generation is skipped.

When `config_path` is provided, image and mesh paths can still be supplied
directly, but solver values are read from the YAML file. To run with fully
explicit solver parameters, call `solve()` without `config_path`.

## Mesh Workflow

### Automatic Mesh Generation

```python
result = solve(
    ref_image="case/star/001.bmp",
    def_image="case/star/002.bmp",
    roi_mask="case/star/003.bmp",
    mesh_dir="case/star/mesh",
    mesh_size=30.0,
    element_type="Q4",
)
```

The generated mesh files are cached as element-specific files such as
`nodes_Q4.txt`, `elements_Q4.txt`, and `Inform_Q4.npy`.

### External Mesh Import

```python
from mesh_dic.mesh_gen import export_boundary, import_external_mesh

export_boundary("case/ring/003.bmp", "ring_boundary.txt")
import_external_mesh("ring_mesh.inp", "case/ring/mesh", element_type="Q4")

result = solve(
    ref_image="case/ring/001.bmp",
    def_image="case/ring/002.bmp",
    roi_mask="case/ring/003.bmp",
    mesh_dir="case/ring/mesh",
    external_file="ring_mesh.inp",
    element_type="Q4",
)
```

Supported external formats include Abaqus `.inp`, Gmsh `.msh`, Nastran `.bdf`,
VTK `.vtu`, and other formats supported by `meshio`.

## Running Example Cases

```powershell
python tests\run_cases.py
```

This runs:

- `case/ring` with T3, Q4, and Q8
- `case/star` with T3, Q4, and Q8

Each result directory contains:

- `U.npy`, `U_init.npy`
- `U_pixel.npy`, `V_pixel.npy`, `field_mask.npy`
- `nodes.npy`, `elements.npy`
- `Exx.npy`, `Eyy.npy`, `Exy.npy`
- `overview.png`
- `meta.txt`

`overview.png` visualizes `U_pixel` and `V_pixel` as FE-interpolated full-field
pixel maps. It does not use scatter plotting or plotting-time interpolation for
the displacement fields.

## Running Tests

```powershell
python tests\test_dic.py
```

or:

```powershell
python -m pytest tests -v
```

The current smoke tests cover imports, config loading, mesh I/O, shape
functions, and FE pixel-field interpolation.

## Development Notes

- Python package code lives under `src/mesh_dic/`.
- C++ core code lives under `src/cpp/`.
- Rebuild after C++ edits with `python -m pip install -e .`.
- Generated meshes and case results are intentionally ignored by Git.

## License

See `LICENSE`.
