tpmslab 0.3.0__tar.gz → 0.3.9.dev12__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.
Files changed (165) hide show
  1. tpmslab-0.3.9.dev12/CHANGELOG.md +376 -0
  2. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/CITATION.cff +1 -1
  3. tpmslab-0.3.9.dev12/MANIFEST.in +17 -0
  4. tpmslab-0.3.9.dev12/PKG-INFO +423 -0
  5. tpmslab-0.3.9.dev12/README.md +391 -0
  6. tpmslab-0.3.9.dev12/Run-ComsolConvergence.cmd +3 -0
  7. tpmslab-0.3.9.dev12/Run-ComsolConvergence.ps1 +18 -0
  8. tpmslab-0.3.9.dev12/SOURCE_ORIGIN.json +10 -0
  9. tpmslab-0.3.9.dev12/Setup-Python.ps1 +22 -0
  10. tpmslab-0.3.9.dev12/Start-TpmsLab.cmd +3 -0
  11. tpmslab-0.3.9.dev12/Start-TpmsLab.ps1 +23 -0
  12. tpmslab-0.3.9.dev12/benchmarks/bcc_crosscompare.py +132 -0
  13. tpmslab-0.3.9.dev12/benchmarks/bcc_figures.py +348 -0
  14. tpmslab-0.3.9.dev12/benchmarks/bcc_vs_kuhn.py +85 -0
  15. tpmslab-0.3.9.dev12/benchmarks/comsol_convergence.py +192 -0
  16. tpmslab-0.3.9.dev12/benchmarks/conditioning_study.py +170 -0
  17. tpmslab-0.3.9.dev12/benchmarks/itt_layers.py +77 -0
  18. tpmslab-0.3.9.dev12/benchmarks/itt_prototype.py +404 -0
  19. tpmslab-0.3.9.dev12/benchmarks/itt_study.py +108 -0
  20. tpmslab-0.3.9.dev12/benchmarks/microgen_worker.py +31 -0
  21. tpmslab-0.3.9.dev12/benchmarks/other_tools.py +123 -0
  22. tpmslab-0.3.9.dev12/benchmarks/quality_vs_gmsh.py +293 -0
  23. tpmslab-0.3.9.dev12/benchmarks/refine_experiment.py +216 -0
  24. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/release_reference.py +14 -6
  25. tpmslab-0.3.9.dev12/benchmarks/snapping_study.py +232 -0
  26. tpmslab-0.3.9.dev12/benchmarks/transport_convergence.py +266 -0
  27. tpmslab-0.3.9.dev12/docs/COMBINED_TPMS.md +79 -0
  28. tpmslab-0.3.9.dev12/docs/COMPARISON_ZH.md +217 -0
  29. tpmslab-0.3.9.dev12/docs/CONVERGENCE_STUDY_ZH.md +72 -0
  30. tpmslab-0.3.9.dev12/docs/HANDOFF_ZH.md +147 -0
  31. tpmslab-0.3.9.dev12/docs/PYPI_PUBLISHING.md +47 -0
  32. tpmslab-0.3.9.dev12/docs/PYTHON_COMSOL_ZH.md +125 -0
  33. tpmslab-0.3.9.dev12/docs/QUALITY_CONDITIONING_ZH.md +80 -0
  34. tpmslab-0.3.9.dev12/docs/QUALITY_REMESH.md +60 -0
  35. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/QUICKSTART_EN.md +119 -95
  36. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/QUICKSTART_ZH.md +62 -53
  37. tpmslab-0.3.9.dev12/docs/RELEASE_0.3.9.dev12.md +32 -0
  38. tpmslab-0.3.9.dev12/docs/RELEASE_NOTES_v0.3.1.md +7 -0
  39. tpmslab-0.3.9.dev12/docs/RELEASE_NOTES_v0.3.3.md +7 -0
  40. tpmslab-0.3.9.dev12/docs/RELEASE_NOTES_v0.3.4.md +7 -0
  41. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/SOLID_FLUID.md +1 -1
  42. tpmslab-0.3.9.dev12/docs/VERTEX_SNAPPING_ZH.md +118 -0
  43. tpmslab-0.3.9.dev12/docs/runtime_hashes_0.3.1.json +15 -0
  44. tpmslab-0.3.9.dev12/examples/combined_gyroid_diamond.json +21 -0
  45. tpmslab-0.3.9.dev12/examples/combined_tpms.py +15 -0
  46. tpmslab-0.3.9.dev12/examples/python_comsol.py +28 -0
  47. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/pyproject.toml +1 -1
  48. tpmslab-0.3.9.dev12/requirements-python-comsol-verified.txt +3 -0
  49. tpmslab-0.3.9.dev12/requirements-quality-verified.txt +4 -0
  50. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/setup.cfg +4 -4
  51. tpmslab-0.3.9.dev12/src/tpmslab/__init__.py +73 -0
  52. tpmslab-0.3.9.dev12/src/tpmslab/batch_smoothing.py +184 -0
  53. tpmslab-0.3.9.dev12/src/tpmslab/cli.py +148 -0
  54. tpmslab-0.3.9.dev12/src/tpmslab/comsol.py +534 -0
  55. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/comsol_audit.py +36 -42
  56. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/comsol_dual.py +76 -22
  57. tpmslab-0.3.9.dev12/src/tpmslab/comsol_remesh.py +336 -0
  58. tpmslab-0.3.9.dev12/src/tpmslab/conditioning.py +307 -0
  59. tpmslab-0.3.9.dev12/src/tpmslab/convergence.py +65 -0
  60. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/io.py +87 -72
  61. tpmslab-0.3.9.dev12/src/tpmslab/model.py +381 -0
  62. tpmslab-0.3.9.dev12/src/tpmslab/multidomain.py +337 -0
  63. tpmslab-0.3.9.dev12/src/tpmslab/optimize.py +925 -0
  64. tpmslab-0.3.9.dev12/src/tpmslab/periodic.py +223 -0
  65. tpmslab-0.3.9.dev12/src/tpmslab/quality.py +284 -0
  66. tpmslab-0.3.9.dev12/src/tpmslab/reporting.py +84 -0
  67. tpmslab-0.3.9.dev12/src/tpmslab/sampling.py +55 -0
  68. tpmslab-0.3.9.dev12/src/tpmslab/snapping.py +293 -0
  69. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/app.js +30 -30
  70. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/index.html +2 -2
  71. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/style.css +2 -0
  72. tpmslab-0.3.9.dev12/src/tpmslab/surface_smoothing.py +421 -0
  73. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/verification.py +4 -2
  74. tpmslab-0.3.9.dev12/src/tpmslab/volume.py +593 -0
  75. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/web.py +319 -302
  76. tpmslab-0.3.9.dev12/src/tpmslab.egg-info/PKG-INFO +423 -0
  77. tpmslab-0.3.9.dev12/src/tpmslab.egg-info/SOURCES.txt +132 -0
  78. tpmslab-0.3.9.dev12/tests/test_bcc_lattice.py +145 -0
  79. tpmslab-0.3.9.dev12/tests/test_benchmark_workflow.py +84 -0
  80. tpmslab-0.3.9.dev12/tests/test_calibration_config.py +45 -0
  81. tpmslab-0.3.9.dev12/tests/test_combined.py +145 -0
  82. tpmslab-0.3.9.dev12/tests/test_comsol_remesh.py +32 -0
  83. tpmslab-0.3.9.dev12/tests/test_comsol_workflow.py +170 -0
  84. tpmslab-0.3.9.dev12/tests/test_conditioning.py +187 -0
  85. tpmslab-0.3.9.dev12/tests/test_convergence.py +38 -0
  86. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/tests/test_core.py +151 -117
  87. tpmslab-0.3.9.dev12/tests/test_edge_projection.py +60 -0
  88. tpmslab-0.3.9.dev12/tests/test_english_runtime.py +38 -0
  89. tpmslab-0.3.9.dev12/tests/test_generation_speed_dev6.py +56 -0
  90. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/tests/test_multidomain.py +13 -1
  91. tpmslab-0.3.9.dev12/tests/test_optimization_budgets_dev6.py +178 -0
  92. tpmslab-0.3.9.dev12/tests/test_optimize.py +171 -0
  93. tpmslab-0.3.9.dev12/tests/test_optimizer_cache_dev7.py +39 -0
  94. tpmslab-0.3.9.dev12/tests/test_periodic.py +39 -0
  95. tpmslab-0.3.9.dev12/tests/test_report_version.py +7 -0
  96. tpmslab-0.3.9.dev12/tests/test_review_fixes.py +283 -0
  97. tpmslab-0.3.9.dev12/tests/test_sampling.py +19 -0
  98. tpmslab-0.3.9.dev12/tests/test_smoothing_dev7.py +101 -0
  99. tpmslab-0.3.9.dev12/tests/test_snapping.py +198 -0
  100. tpmslab-0.3.9.dev12/tests/test_speed_dev7.py +73 -0
  101. tpmslab-0.3.9.dev12/tests/test_speed_paths.py +96 -0
  102. tpmslab-0.3.9.dev12/tests/test_surface_guard_dev6.py +110 -0
  103. tpmslab-0.3.0/.zenodo.json +0 -24
  104. tpmslab-0.3.0/CHANGELOG.md +0 -32
  105. tpmslab-0.3.0/MANIFEST.in +0 -12
  106. tpmslab-0.3.0/PKG-INFO +0 -220
  107. tpmslab-0.3.0/README.md +0 -188
  108. tpmslab-0.3.0/src/tpmslab/__init__.py +0 -30
  109. tpmslab-0.3.0/src/tpmslab/cli.py +0 -63
  110. tpmslab-0.3.0/src/tpmslab/comsol.py +0 -250
  111. tpmslab-0.3.0/src/tpmslab/model.py +0 -258
  112. tpmslab-0.3.0/src/tpmslab/multidomain.py +0 -196
  113. tpmslab-0.3.0/src/tpmslab/quality.py +0 -46
  114. tpmslab-0.3.0/src/tpmslab/volume.py +0 -310
  115. tpmslab-0.3.0/src/tpmslab.egg-info/PKG-INFO +0 -220
  116. tpmslab-0.3.0/src/tpmslab.egg-info/SOURCES.txt +0 -78
  117. tpmslab-0.3.0/validation/README.md +0 -44
  118. tpmslab-0.3.0/validation/checksums.json +0 -18
  119. tpmslab-0.3.0/validation/code_commit.json +0 -4
  120. tpmslab-0.3.0/validation/density/density_results.json +0 -404
  121. tpmslab-0.3.0/validation/environment.json +0 -23
  122. tpmslab-0.3.0/validation/existing_Diamond_audit/audit.json +0 -35
  123. tpmslab-0.3.0/validation/existing_Gyroid_audit/audit.json +0 -35
  124. tpmslab-0.3.0/validation/existing_Primitive_Schwartz_audit/audit.json +0 -35
  125. tpmslab-0.3.0/validation/historical_windows_checksums.json +0 -17
  126. tpmslab-0.3.0/validation/performance_summary.csv +0 -5
  127. tpmslab-0.3.0/validation/provenance.json +0 -72
  128. tpmslab-0.3.0/validation/quality_summary.csv +0 -5
  129. tpmslab-0.3.0/validation/reference_configs/Diamond.json +0 -33
  130. tpmslab-0.3.0/validation/reference_configs/Gyroid.json +0 -33
  131. tpmslab-0.3.0/validation/reference_configs/Primitive_Schwartz.json +0 -33
  132. tpmslab-0.3.0/validation/refinement_summary.csv +0 -10
  133. tpmslab-0.3.0/validation/summary.json +0 -606
  134. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/LICENSE +0 -0
  135. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/THIRD_PARTY_NOTICES.md +0 -0
  136. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/density_study.py +0 -0
  137. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/revision_study.py +0 -0
  138. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/run_benchmarks.py +0 -0
  139. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/verify_comsol.py +0 -0
  140. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/benchmarks/verify_solid_fluid.py +0 -0
  141. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/METHOD.md +0 -0
  142. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/RELEASE_NOTES_v0.3.0.md +0 -0
  143. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/VALIDATION.md +0 -0
  144. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/VERIFICATION.md +0 -0
  145. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/VERSION_0.3.0.md +0 -0
  146. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/docs/lattgen_reference.m +0 -0
  147. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/graded_gyroid.json +0 -0
  148. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/graded_gyroid.py +0 -0
  149. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/gyroid_graded.json +0 -0
  150. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/primitive_graded.json +0 -0
  151. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/solid_fluid.json +0 -0
  152. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/examples/solid_fluid_api.py +0 -0
  153. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/licenses/LattGen-MIT.txt +0 -0
  154. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/__main__.py +0 -0
  155. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/families.json +0 -0
  156. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/py.typed +0 -0
  157. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/vendor/OrbitControls.js +0 -0
  158. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/vendor/THREE-LICENSE.txt +0 -0
  159. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab/static/vendor/three.module.js +0 -0
  160. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab.egg-info/dependency_links.txt +0 -0
  161. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab.egg-info/entry_points.txt +0 -0
  162. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab.egg-info/requires.txt +0 -0
  163. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/src/tpmslab.egg-info/top_level.txt +0 -0
  164. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/tests/test_package.py +0 -0
  165. {tpmslab-0.3.0 → tpmslab-0.3.9.dev12}/tests/test_verification.py +0 -0
@@ -0,0 +1,376 @@
1
+ # 0.3.9.dev12 — linear tetrahedron export
2
+
3
+ - Remove the optional 10-node curved export and its COMSOL import validation case.
4
+ The NAS and NPZ exports contain four-node tetrahedra.
5
+
6
+ # 0.3.9.dev11 — optional surface envelope; hand-off (2026-11-05)
7
+
8
+ - `optimize_mesh(..., surface_envelope=mm)` (CLI `--surface-envelope`):
9
+ interface nodes may leave the exact implicit surface by at most this
10
+ first-order distance |g|/|grad g| when that improves the local worst quality
11
+ (fTetWild-style envelope; default None keeps the exact surface). The maximum
12
+ deviation is checked and reported (`optimization.surface_deviation_max_mm`).
13
+ With effort="high" and 8.66 µm (fTetWild's default 1e-3 of the box diagonal)
14
+ over the 16 bcc_crosscompare cases: median solid p01 0.62, median minimum
15
+ 0.48; versus fTetWild on the same boundary p01 higher in 15/16, minimum
16
+ higher in 15/16, faster in 16/16 (1.4–4.2x), but solid volume error lower
17
+ in only 4/16 (typically +0.01 to +0.1 pp higher; the envelope moves are not
18
+ volume-neutral yet).
19
+ - docs/HANDOFF_ZH.md: state, architecture, reproduction commands and the open
20
+ task list for the next maintainer.
21
+
22
+ # 0.3.9.dev10 — high-effort optimisation (2026-11-05)
23
+
24
+ - `optimize_mesh(..., effort="high")` (CLI `--optimize-effort high`, web
25
+ "高质量优化"): every cell below quality 0.7 is targeted instead of 0.5. The
26
+ standard threshold capped the BCC solid p01 near 0.52 at every resolution.
27
+ 16 bcc_crosscompare cases (BCC α 0.3 / boundary 0.35): median p01 0.51 →
28
+ 0.57 (up to 0.66), median end-to-end time 2.7 s → 4.1 s. Against fTetWild on
29
+ the same boundary (single thread): p01 higher in 12 of 16 cases, solid volume
30
+ error lower in 15 of 16, 2–5× less time; fTetWild keeps a higher minimum in
31
+ 8 of 16 (mostly Diamond and IWP box layers) and higher p01 on the coarsest
32
+ Diamond/IWP levels.
33
+ - Edge-removal candidates are scored with the same scalar arithmetic but
34
+ without per-call cache overhead (identical meshes; about 7 % less time).
35
+
36
+ # 0.3.9.dev9 — box-layer snapping, curved quadratic export, periodic faces (2026-11-05)
37
+
38
+ - `Config.snap_alpha_boundary` (CLI `--snap-alpha-boundary`): separate snap
39
+ threshold for lattice vertices on the outer box. Diagnosis on the BCC meshes:
40
+ 80–100 % of the worst 1 % cells touch the box, mostly where the TPMS meets a
41
+ box face at a shallow angle. With BCC α 0.3 / boundary 0.35 over the 16
42
+ bcc_crosscompare cases: solid p01 up in 12 and down in 2 (at most −0.013),
43
+ solid minimum up in 8 and down in 1 (−0.003), volume error unchanged within
44
+ ±0.05 pp. 0.4 produced a degenerate case (Diamond r10) and is not recommended.
45
+ Default None keeps dev8 arrays.
46
+ - `make_quadratic(model)` / `save_model(..., quadratic=True)` / CLI
47
+ `--quadratic`: `mesh_quadratic.nas` with 10-node CTETRA and CTRIA6; mid-edge
48
+ nodes of implicit-surface edges lie on the exact level set (box planes kept
49
+ flat, both phases share them). Jacobian sampled at 19 points per element;
50
+ curvature halved where det J / det J_linear < 0.2. Solid volume error versus
51
+ the 256³ integral drops 5–64× (e.g. Gyroid r13 0.335 → 0.006 pp); solid +
52
+ fluid still fill the box exactly. COMSOL import of the 10-node file is not
53
+ yet verified (evidence/run_dev9_validation.py).
54
+ - `Config.periodic_faces` (CLI `--periodic-faces`): on every axis where the
55
+ field repeats (checked numerically), opposite faces get identical node sets
56
+ and triangulations: field samples copied, snaps paired, coordinates enforced
57
+ and `report["periodic"]` verified after generation and optimisation. The
58
+ optimiser moves paired face nodes together and skips face retriangulation
59
+ there (p01 Gyroid 0.511 → 0.505, Diamond 0.504 → 0.492; about 2× slower).
60
+ - `report["wall_resolution"]` for sheets: 2q/|∇f| wall thickness against the
61
+ lattice spacing, with a warning when the thinnest 5 % is under one cell.
62
+ - Optimiser incidence is built by array grouping: identical meshes, 14 % less
63
+ optimisation time on the 12-case BCC timing set.
64
+ - Not adopted: thin-wall adaptive edge bisection (benchmarks/refine_experiment.py)
65
+ did not beat uniform BCC at equal element count (Diamond_low and Gyroid
66
+ 0.08→0.5, P1 k_eff) and was 2–4× slower.
67
+ - Benchmarks: bcc_crosscompare.py, other_tools.py (TetGen, fTetWild, microgen),
68
+ quadratic_volume.py, bcc_figures.py; validation launcher Run-Dev9Validation.cmd.
69
+
70
+ # 0.3.9.dev8 — optional body-centred cubic background lattice (2026-11-05)
71
+
72
+ - New `Config.lattice = "kuhn" | "bcc"` (CLI `--lattice`, web "背景格子").
73
+ `bcc` adds voxel centres and box-face centres; every pair of face-adjacent
74
+ voxels contributes four congruent tetrahedra (mean ratio 0.952, dihedral
75
+ angles 60°/90°), and each box-face square is coned through its face centre
76
+ (four half tetrahedra, mean ratio 0.800). The background is conforming to
77
+ the box faces, so clipping, snapping, implicit-root cuts, two-phase
78
+ generation and `optimize_mesh` are unchanged. Default stays `kuhn`.
79
+ - BCC has about twice the tetrahedra per voxel: use about 5/6 of the Kuhn
80
+ resolution for a similar element count. Recommended with `snap_alpha=0.3`
81
+ (web UI uses 0.3 for BCC, 0.25 for Kuhn).
82
+ - `benchmarks/bcc_vs_kuhn.py`: four quality_vs_gmsh designs, Kuhn r12/r16
83
+ (α 0.25) vs BCC r10/r13 (α 0.3), optimised: solid p01 higher in 6 of 8
84
+ cases (equal in one, −0.013 in one), minimum higher in 7 of 8, median
85
+ +0.07 to +0.17 in all, volume error within ±0.07 pp of Kuhn, generate +
86
+ optimise 1.1–3.8× faster. Larger α (0.4, or 0.25/0.40 by edge length) raises
87
+ quality further on some designs but increases the volume error.
88
+ - Per-voxel density bookkeeping uses an explicit background-to-voxel owner
89
+ map instead of `owner // 6`.
90
+ - `benchmarks/itt_*.py`: stage-0 prototype of template inheritance and
91
+ iso-surface transport (not part of the package; see evidence/itt_stage0).
92
+
93
+ # 0.3.9.dev7 — less repeated work and phase-aware surface moves (2026-11-05)
94
+
95
+ - Generation reuses SVD polygon ordering only for shared faces with exactly
96
+ matching vertex IDs and order. Scalar fan screening rejects clear failures;
97
+ close decisions and accepted fans retain the original NumPy arithmetic.
98
+ - Cache ordered-tetrahedron metrics during reconnection, up to 65,536 entries;
99
+ invalidate on every coordinate refresh. The cache preserves signed volume
100
+ and does not change numerical decisions.
101
+ - Evaluate chord error on actual incident faces, without padded five-dimensional
102
+ triangle copies; skip candidates already excluded by quality or orientation.
103
+ - Mixed-phase surface moves preserve each phase's local minimum quality.
104
+ Round-level quality, median, chord and volume budgets remain unchanged.
105
+ This can retain more rounds and improve final quality, with a design-dependent
106
+ time cost. Record rejected phase trials in each round's history.
107
+ - Add numerical regressions for scalar screening, cache invalidation, packed
108
+ chord errors and per-phase trial acceptance.
109
+
110
+ # 0.3.9.dev6 — generation work reuse and geometry budgets (2026-11-05)
111
+
112
+ - Generation reuses face incidence for connected components, precomputes face
113
+ masks, and batches shared-vertex coordinate validation in two-phase meshes.
114
+ - Surface smoothing recomputes hard chord guards against the current geometry
115
+ of each independent batch, with bounded chunk memory. `optimize_mesh` now
116
+ defaults to `chord_tolerance=0.0`; explicit `None` retains soft ranking only.
117
+ - Each optimisation round checks per-phase minimum/p01/poor-volume quality,
118
+ the existing median-loss budget, and cumulative phase-volume drift (default
119
+ 0.3 percentage points of box volume; configurable or `None`). A failed round
120
+ restores the previous mesh and records its rejection reasons.
121
+ - Recompute density profiles, domain/phase volumes, counts and interface area
122
+ from the final mesh. Profile `slab_count` records unequal-bin weights.
123
+ - Rebuild current boundaries before optional SLSQP conditioning. Clear input
124
+ COMSOL solve evidence after optimisation.
125
+ - Add regressions for live-neighbour chord guards, exact rollback, geometry
126
+ reports, SLSQP boundaries, shared-coordinate validation and face components.
127
+
128
+ # 0.3.9.dev5 — speed (2026-11-05)
129
+
130
+ - Generation: identical meshes (mesh_sha256 checked on eight configurations
131
+ against 0.3.9.dev3), about 30% faster.
132
+ - `choose_fan` scores its 3-10 cell fans with scalar volume / edge-length
133
+ arithmetic that reproduces numpy's bit for bit (the 3-term `einsum` order
134
+ is detected at import against the local numpy; `pow` stays in numpy);
135
+ falls back to the numpy path if no order matches.
136
+ - `quality.unique_rows` packs integer rows into one int64 key: identical
137
+ output to `np.unique(axis=0)`, several times faster; used for face/edge
138
+ incidence in generation, two-phase partition, conditioning and audits.
139
+ - `boundary_digest` is vectorised (same stable sorts, same bytes).
140
+ - Expressions are compiled once (whitelisted AST, empty builtins) instead of
141
+ walked node by node on every evaluation; values are bitwise identical.
142
+ - `optimize_mesh`: about 2x faster than 0.3.9.dev4 at equal or better quality.
143
+ - New `tpmslab.batch_smoothing`: interior and surface smoothing move
144
+ independent vertex sets (stars sharing no cell) together; all trial
145
+ positions of a batch are scored in one pass with the vertex-affine volume
146
+ and vertex-quadratic edge-length forms, without materialising the moved
147
+ tetrahedra.
148
+ - Adjacency is built once per round and shared; boundary arrays for the
149
+ surface step come from the mesh bookkeeping; oriented arrays are rebuilt
150
+ once at the end.
151
+ - The chord-error criterion uses one |grad g| per candidate vertex (six
152
+ fewer field evaluations per triangle centroid); cap flips compare
153
+ area x |g| directly.
154
+ - Mesh results of `optimize=True` change (Jacobi-style batches instead of
155
+ vertex-by-vertex order); default meshes do not.
156
+
157
+ # 0.3.9.dev4 — faster, stronger cut-layer optimisation (2026-11-05)
158
+
159
+ - Local mesh operations score their 1-20 cell stars in pure Python
160
+ (`quality.tet_scalar`/`star_scalar`) or one vectorised pass over all trial
161
+ positions (`quality.star_trials`) instead of one numpy call per star;
162
+ numpy call overhead was ~95% of the dev3 optimiser time.
163
+ - General Shewchuk-style edge removal (`_Mesh.remove_edge`): an interior edge
164
+ with a ring of 3-7 tetrahedra is replaced by the maximin triangulation of
165
+ its ring (O(n^3) dynamic programme); 3-2 and 4-4 flips are the n=3 and n=4
166
+ cases. Candidate edges/faces that failed are not retried within a round.
167
+ - Interior and surface smoothing try two directions per vertex (neighbour
168
+ centroid and the point that makes the worst incident cell regular) at four
169
+ step lengths and keep the best admissible one.
170
+ - Each round works on the quality tail (cells below the 5% quantile, never
171
+ above `quality_threshold`), `focus_quantile=0.05`.
172
+ - Surface moves are chosen with a chord-error criterion: among positions that
173
+ reach at least `chord_gain_floor` (0.1) of the best quality gain, the one
174
+ whose incident surface triangles depart least from the level set
175
+ (area x |g|/|grad g| at the centroids) is taken. An optional hard gate is
176
+ `chord_tolerance`. Without this, the stronger smoothing moved the phase
177
+ volume away from the exact implicit volume on coarse meshes.
178
+ - The per-round SLSQP `condition_mesh` pass is no longer part of the default
179
+ `smooth=True` path (it changed no p01/minimum value in the study);
180
+ `smooth="slsqp"` keeps it.
181
+ - Tests: edge removal on a five-cell ring, vectorised star trials, and the
182
+ optimise test now asserts that the solid volume does not move away from a
183
+ 128^3 midpoint integral of the exact field (was: shift < 0.1 pp).
184
+ - Box-face edge removal (`_Mesh.remove_boundary_edge`): an edge lying in a
185
+ flat box face, whose two box-face triangles are coplanar, is removed with
186
+ its open ring; the face quad takes the other diagonal. Region, box faces
187
+ and phase volumes are exactly unchanged.
188
+ - Interface cap flips (`_Mesh.cap_flip`, two-phase, `surface=True` only): a
189
+ cell with all four vertices on the interface and two interface faces is
190
+ handed to the other phase (the interface takes the other triangulation of
191
+ the same four surface points) and its now-interior edge is removed; kept
192
+ only when quality improves and the new interface triangles are not further
193
+ from the level set. Interface conformity, triangle counts per boundary id
194
+ and connectivity are preserved; exterior/interface arrays are rebuilt.
195
+ - Default meshes (optimize=False) are unchanged.
196
+
197
+ # 0.3.9.dev3 — cut-layer mesh optimisation (2026-11-05)
198
+
199
+ - New `optimize_mesh` (`tpmslab.optimize`, `generate(..., optimize=True)`,
200
+ `tpmslab generate --optimize`, browser checkbox): local reconnection of the
201
+ cut layer (2-3, 3-2 and 4-4 flips restricted to interior faces/edges),
202
+ maximin Laplacian interior smoothing with SLSQP refinement of the poorest
203
+ stars, and `tpmslab.surface_smoothing`: boundary vertices slide within the
204
+ box faces and *along the exact implicit level set* (vectorised Newton
205
+ re-projection, residual < 1e-9 mm). Exterior/interface connectivity, phase
206
+ and domain labels are unchanged; phase volumes shift by ~0.01 pp; the
207
+ result is audited (`quality_audit`, interface, box planes, residuals).
208
+ - `benchmarks/quality_vs_gmsh.py`: like-for-like comparison with Gmsh on the
209
+ same boundary polyhedron (fixed boundary, interior only) and with Gmsh
210
+ re-meshing the surface as well; see docs/COMPARISON_ZH.md for numbers.
211
+ - `condition_mesh(max_median_loss=...)` exposes the median-loss budget of the
212
+ non-regression gate (default unchanged, 5%).
213
+ - `quality.cross` / `quality.signed_volumes`: fast small-array helpers.
214
+ - Default meshes (optimize=False) are unchanged from 0.3.9.dev2.
215
+ - Not yet run in COMSOL: `evidence/run_dev2_validation.py` gained an
216
+ `optimized_r12` case (flow and elasticity on optimised meshes).
217
+
218
+ # 0.3.9.dev2 — review fixes (2026-11-05)
219
+
220
+ Read-only review of 0.3.9.dev1 followed by these changes. No COMSOL run was
221
+ made for this version; see `evidence/README.md` for what the shipped
222
+ evidence does and does not cover.
223
+
224
+ - Evidence: rebuild `evidence/authorized_smoke_summary.json` from the attempt
225
+ records (both smoke cases passed on their second attempt; the first-attempt
226
+ summary is kept as `authorized_smoke_summary.first_attempt.json`); make
227
+ `evidence/run_authorized_smoke.py` idempotent; add `evidence/README.md`.
228
+ - One COMSOL launcher (`tpmslab.comsol.run_comsol_class`) for the
229
+ elasticity/flow bridge, `comsol_remesh` and `comsol_audit`: 6.2/6.3 mesh
230
+ API reflection, isolated `-prefsdir`, short `-tmpdir/-recoverydir/-data`
231
+ paths, log capture, marker parsing and the COMSOL version string recorded
232
+ in `run.json`/`comsol_verification.json`. `remesh-quality` previously used a
233
+ hard-coded `geometricModel("")` that does not compile on 6.2.
234
+ - `volume_components` now counts connectivity through shared faces in both
235
+ single- and two-phase modes; vertex/edge-only contacts are reported as
236
+ `pinched_contacts` with a warning instead of counting as one body.
237
+ - Reopen check compares the integrated volume with a relative tolerance
238
+ (was an absolute 1e-15 m^3).
239
+ - Pre-flight estimate of the background-lattice memory; oversized
240
+ `cells`×`resolution` fail with an explicit message (limit adjustable via
241
+ `TPMSLAB_MAX_LATTICE_BYTES`).
242
+ - Two-phase generation samples, calibrates, audits and snaps the lattice
243
+ once and shares it between the solid and complementary passes.
244
+ - `edge_interpolation="implicit_root"` uses vectorised bracketed bisection
245
+ started from the linear cut instead of per-edge `brentq`; the
246
+ unbracketed-cut fallback is unchanged. All other modes produce
247
+ byte-identical meshes to 0.3.9.dev1 (checked by mesh_sha256 on seven
248
+ configurations). `implicit_root` meshes differ only on edges where the
249
+ field grazes zero several times within a few micrometres (12 of 5001
250
+ nodes, at most 4.3 um, in the n=10 Gyroid check): both versions return
251
+ a point on the implicit surface, but not always the same one.
252
+ - Two-phase `density_profile` is recomputed from the final (projected) solid
253
+ cells; `density_profile_method` names the binning.
254
+ - Off-grid sampling probes run for built-in families as well; custom
255
+ formulas are still rejected on a miss, built-in families get a warning.
256
+ - Flow demo restricts `spf` to fluid domains that connect Z- and Z+ and
257
+ records `excluded_fluid_domains`; only a model without any spanning
258
+ channel is rejected.
259
+ - `element_order` (1 or 2) and `processes` (`-np`) options on `build_mph`,
260
+ `run_comsol`, the CLI and the convergence benchmark; recorded per attempt.
261
+ Order 2 is not yet covered by any shipped evidence.
262
+ - `generate --mph/--solve` accepts the same launch options as `comsol`.
263
+ - The browser COMSOL path no longer deletes the previous top-level
264
+ verification file; `build_mph` preserves it inside the new attempt.
265
+ - Documentation: version wording aligned with the 6.2.0.290 evidence.
266
+
267
+ # 0.3.9.dev1 — isolated COMSOL execution
268
+
269
+ - Explicit per-attempt preference files, CLI and benchmark options; global preferences unchanged.
270
+ - Short native temporary, recovery and workspace paths prevent Windows path-length failures.
271
+ - Actual COMSOL 6.2 solid and pore-flow smoke checks and documented comparison with related tools.
272
+
273
+ # 0.3.9.dev0 — Python to COMSOL workflow
274
+
275
+ - Correct nonuniform three-grid power-law fits and document the revised estimates.
276
+ - Preserve a separate, input-hashed directory for each COMSOL attempt; clear failed current state.
277
+ - Add run_comsol API and a comsol CLI command for saved models and material settings.
278
+ - Fix empty-cut projection and add bounded off-grid probes for custom formulas.
279
+ - Check compiler output as well as exit status; support 6.2/6.3 mesh API signatures.
280
+ - Checkpoint convergence rows, resume studies, fix Gmsh cleanup and label elasticity snapping accurately.
281
+ - Stream hashes; preserve historical delivery records under history/pre_0.3.9.
282
+ - Real COMSOL 6.2 Java compilation succeeded for both smoke cases; NAS import blocked by file-system security preferences. No successful solver validation is claimed.
283
+
284
+ # 0.3.8.dev0 (local improvement build; not published)
285
+
286
+ - Add opt-in pre-cut lattice-vertex snapping (`Config.snap_alpha`, `--snap-alpha`): a lattice vertex within `snap_alpha` of a cut point along one of its lattice edges is moved onto the isosurface before clipping, so the near-degenerate sliver that cut would have produced is never created. Default `snap_alpha=0` leaves every existing output byte-identical.
287
+ - Snap onto the exact implicit root by default (`snap_target="implicit"`); `"linear"` keeps the linear-cut point. Outer-box nodes may only move within their box face; moves that would invert a background tetrahedron, flatten a tetrahedron onto one isosurface, or pinch the material or its complement along a lattice edge are reverted and counted in `report["vertex_snapping"]`.
288
+ - Snapping is applied to the full inequality set before any fluid-side sign flip, so complementary solid/fluid passes share identical vertices and cut keys; the interface audit, box-face audit and scalar-diffusion patch check pass on all 12 study designs.
289
+ - Add `benchmarks/snapping_study.py` (12 paired designs, three variants, recomputed statistics, dense-sample reference density and implicit-surface fidelity) and `tests/test_snapping.py`.
290
+ - Allow `snap_alpha` together with `edge_interpolation="implicit_root"` / `"quadratic_root"`: root projection now uses the snapped lattice coordinates and keeps the linear cut when the true field does not bracket a root (`report["edge_root_unbracketed_cuts"]`). With both enabled every interface node lies on the implicit surface; the median solid-density error drops from 1.52 to 0.69 pp (worst 3.66 -> 2.03 pp) while the Q<0.01 count stays at 1 on the 12 designs.
291
+ - Add a browser checkbox (切割前顶点吸附) that sets `snap_alpha=0.25`, restore it from saved parameters, and show snapped/reverted vertex counts in the result notes.
292
+ - Measured on the 12 designs at `snap_alpha=0.25`: aggregate Q<0.01 cells 2710 -> 1 (Q<0.1: 60217 -> 250), tetrahedra 489696 -> 211328, per-phase minimum quality typically 0.001-0.01 -> 0.08-0.18. Costs: median absolute solid-density error unchanged (1.52 -> 1.51 pp) but the worst case rises (3.66 -> 4.03 pp); interface-node RMS distance to the implicit surface rises 10-25 % (10-40 um at 5 mm / resolution 12). No solver-accuracy or speedup claim is made.
293
+
294
+ # 0.3.7.dev0 (local improvement build; not published)
295
+
296
+ - Add bounded interior maximin smoothing with analytic quality derivatives and unchanged boundary/interface nodes, connectivity, domains and phase labels.
297
+ - Reconstruct input cell incidence; reject inverted cells, duplicates, nonmanifold faces and missing boundary/interface declarations.
298
+ - Audit candidates independently of optimizer success. Enforce phase minimum/p01/poor-count non-regression, a 5% relative median-loss budget and per-domain volume retention; roll back failed candidates with evidence.
299
+ - Expose `condition_mesh`, `quality_audit`, `generate(..., condition=True)`, CLI flags and a browser checkbox. Optional quality thresholds reject before export.
300
+ - Include 12 paired mesh records with independent geometry and exact scalar-diffusion patch checks. Do not infer FE/CFD accuracy or speedup from geometric quality alone.
301
+
302
+ # 0.3.6.dev0 (local development source; not a public release)
303
+
304
+ - Add `combine="blend"` for spatial transitions between two built-in or custom TPMS fields.
305
+ - Expose the secondary family, transition axis and bounds, weight profile, and calibration weight-sample count in Python, JSON, and the local browser interface.
306
+ - Calibrate the blended field using fixed-weight periodic quantiles; preserve exact original fields outside the transition and when both expressions are identical.
307
+ - Use one blended field for complementary solid/pore meshes and root interpolation, and export complete combined-design metadata.
308
+ - Add tests, a Python example, a JSON example, and combined-geometry documentation. The feature adds one composite solid phase and its complementary pore phase.
309
+ - Preserve frozen experiment sources and unchanged default mesh arrays; this feature has not established a mesh-quality or FEM accuracy advantage.
310
+
311
+ # 0.3.5.dev0 (local experimental source; not a public release)
312
+
313
+ - Add an optional COMSOL-native `RemeshFaces` plus `FreeTet` workflow for already verified two-phase exports.
314
+ - Require save/reopen, preserved domain and boundary selections, exact cross-phase face incidence, volume and interface-area tolerances, and improved solid quality before accepting the output.
315
+ - Add opt-in `edge_interpolation="implicit_root"` for two-phase meshes. It projects shared cut vertices to implicit-field edge roots subject to local positive-tetrahedron checks; the default remains linear interpolation.
316
+ - Add experimental `edge_interpolation="quadratic_root"`: batch-evaluate the continuous field at three positions on each cut edge, fit a quadratic crossing, and apply the same inversion guard to both phases. It offers a lower-cost approximation to iterative exact roots in the tested graded designs.
317
+ - Keep COMSOL external and optional. Preserve the 0.3.4 direct-mesh benchmark provenance separately from these exploratory modes.
318
+
319
+ # 0.3.4
320
+
321
+ - Add configurable density-calibration sampling via `m_cal` (default 56).
322
+
323
+ - Remove fixed upper limits on per-cell resolution and per-axis cell counts.
324
+ - Use an uncapped integer input in the browser interface.
325
+ - Preserve lower bounds, integer validation and numerical algorithms.
326
+
327
+ # 0.3.3
328
+
329
+ - Set the per-cell resolution maximum to 48 in Python and the browser slider.
330
+ - Retain removal of the total background-grid cap.
331
+ - Synchronize documentation and add boundary regression checks.
332
+ - Report the running generator version instead of a stale literal; geometry is unchanged.
333
+
334
+ # 0.3.2
335
+
336
+ - Remove the fixed 200,000-background-voxel limit from configuration validation.
337
+ - Retain per-axis cell-count and per-cell resolution validation.
338
+ - Add configuration regression coverage for grids above the former limit.
339
+
340
+ # 0.3.1
341
+
342
+ - Use English for Python progress callbacks, exceptions, API messages and exported warnings.
343
+ - Update generator metadata; preserve numerical algorithms and historical validation records.
344
+
345
+ # Changelog
346
+
347
+ ## 0.3.0
348
+
349
+ - Package the verified complementary solid/fluid workflow and independent audits.
350
+ - Include density, refinement, interface, channel and performance records with provenance.
351
+ - Retain the validated numerical implementation from commit 686b783e0385.
352
+ - Clarify geometry/solver response stability and local quality-strategy limitations.
353
+ - Add isolated-wheel reference checks, exact-commit release preparation and public version documentation.
354
+ - Preserve historical validation provenance; GitHub publication and DOI registration remain separate records.
355
+
356
+
357
+ ## 0.3.0rc1 — solid and pore-fluid domains
358
+
359
+ - Add complementary solid/fluid meshes with shared interface vertices and faces.
360
+ - Preserve independently connected solid and fluid domains, phase arrays and named boundaries.
361
+ - Add fluid preview, domain metadata and optional COMSOL named selections.
362
+ - Verify three fixed-wall pore-flow examples in COMSOL; deformation-coupled FSI is not implemented.
363
+ - Add analytical partition and multi-family interface regression tests.
364
+
365
+ ## 0.2.0rc1 — local release candidate
366
+
367
+ - Introduce src-layout packaging, public Python API and command-line commands.
368
+ - Keep Flask and the browser interface optional; COMSOL remains optional.
369
+ - Add conservative interior-fan selection with unchanged external boundary.
370
+ - Add quality-tail diagnostics, deterministic mesh/boundary fingerprints,
371
+ environment records and file-integrity manifests.
372
+ - Normalize configuration lists to immutable tuples and apply phase controls
373
+ consistently in the field helper.
374
+ - Include reproducible comparisons, automated tests and release documentation.
375
+
376
+ Earlier rc entries describe local release candidates.
@@ -2,7 +2,7 @@ cff-version: 1.2.0
2
2
  message: "Please cite the exact software version used."
3
3
  type: software
4
4
  title: "TPMS Lab"
5
- version: "0.3.0"
5
+ version: "0.3.9.dev12"
6
6
  authors:
7
7
  - family-names: Chen
8
8
  given-names: Xin
@@ -0,0 +1,17 @@
1
+ include README.md LICENSE CHANGELOG.md THIRD_PARTY_NOTICES.md
2
+ recursive-include licenses *.txt
3
+ recursive-include docs *.md *.m
4
+ recursive-include examples *.json *.py
5
+ recursive-include tests *.py
6
+ include CITATION.cff
7
+ include requirements-quality-verified.txt
8
+ include Start-TpmsLab.ps1
9
+ include Start-TpmsLab.cmd
10
+ include Setup-Python.ps1
11
+ include Run-ComsolConvergence.ps1
12
+ include Run-ComsolConvergence.cmd
13
+ include requirements-python-comsol-verified.txt
14
+ include SOURCE_ORIGIN.json
15
+ recursive-include benchmarks *.py
16
+
17
+ include docs/runtime_hashes_0.3.1.json