htpolynet 2.2.0__tar.gz → 2.3.1__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 (334) hide show
  1. htpolynet-2.3.1/.claude/skills/htpolynet/SKILL.md +71 -0
  2. {htpolynet-2.2.0 → htpolynet-2.3.1}/CHANGELOG.md +149 -0
  3. {htpolynet-2.2.0 → htpolynet-2.3.1}/CITATION.cff +6 -0
  4. {htpolynet-2.2.0 → htpolynet-2.3.1}/PKG-INFO +2 -1
  5. {htpolynet-2.2.0 → htpolynet-2.3.1}/README.md +1 -0
  6. htpolynet-2.3.1/ROADMAP.md +373 -0
  7. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +16 -0
  8. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/htpolynetpackage.rst +5 -0
  9. htpolynet-2.3.1/docs/source/user-guide/building-a-system.rst +172 -0
  10. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-run.rst +14 -0
  11. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/index.rst +1 -0
  12. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/usage.rst +50 -11
  13. {htpolynet-2.2.0 → htpolynet-2.3.1}/pyproject.toml +1 -1
  14. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/analyze.py +1 -1
  15. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/postsim.py +1 -1
  16. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cli.py +2 -2
  17. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/molecule.py +7 -0
  18. htpolynet-2.3.1/src/htpolynet/core/paramcache.py +132 -0
  19. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/projectfilesystem.py +26 -2
  20. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/runtime.py +118 -7
  21. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/ambertools.py +23 -4
  22. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/software.py +18 -2
  23. htpolynet-2.3.1/tests/unit/test_paramcache.py +342 -0
  24. htpolynet-2.3.1/tests/unit/test_paramcache_ambertools.py +198 -0
  25. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_projectfilesystem.py +51 -0
  26. htpolynet-2.3.1/tests/unit/test_software_provenance.py +61 -0
  27. htpolynet-2.2.0/ROADMAP.md +0 -116
  28. {htpolynet-2.2.0 → htpolynet-2.3.1}/.claude/settings.json +0 -0
  29. {htpolynet-2.2.0 → htpolynet-2.3.1}/.envrc +0 -0
  30. {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/conda-forge-sync.yml +0 -0
  31. {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/docker.yml +0 -0
  32. {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/release.yaml +0 -0
  33. {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/test.yml +0 -0
  34. {htpolynet-2.2.0 → htpolynet-2.3.1}/.gitignore +0 -0
  35. {htpolynet-2.2.0 → htpolynet-2.3.1}/.readthedocs.yaml +0 -0
  36. {htpolynet-2.2.0 → htpolynet-2.3.1}/CLAUDE.md +0 -0
  37. {htpolynet-2.2.0 → htpolynet-2.3.1}/LICENSE +0 -0
  38. {htpolynet-2.2.0 → htpolynet-2.3.1}/MANIFEST.in +0 -0
  39. {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/Dockerfile +0 -0
  40. {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/compose.yml +0 -0
  41. {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/docker-entrypoint.sh +0 -0
  42. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/Makefile +0 -0
  43. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/README.rst +0 -0
  44. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/make.bat +0 -0
  45. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/requirements.txt +0 -0
  46. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/_static/.gitkeep +0 -0
  47. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/changelog.rst +0 -0
  48. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/conf.py +0 -0
  49. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
  50. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
  51. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
  52. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
  53. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
  54. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
  55. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
  56. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
  57. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
  58. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
  59. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
  60. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
  61. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
  62. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  63. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  64. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  65. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  66. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  67. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
  68. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  69. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  70. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  71. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
  72. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
  73. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
  74. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
  75. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
  76. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
  77. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
  78. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
  79. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
  80. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
  81. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
  82. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  83. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  84. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  85. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
  86. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
  87. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
  88. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
  89. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  90. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  91. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  92. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
  93. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  94. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
  95. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
  96. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
  97. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
  98. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
  99. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
  100. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
  101. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
  102. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
  103. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
  104. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
  105. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
  106. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
  107. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
  108. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
  109. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  110. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  111. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  112. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
  113. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  114. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  115. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  116. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
  117. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
  118. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
  119. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
  120. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
  121. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
  122. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
  123. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
  124. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
  125. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
  126. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
  127. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
  128. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  129. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
  130. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
  131. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
  132. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
  133. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
  134. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
  135. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
  136. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
  137. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
  138. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
  139. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
  140. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  141. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  142. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  143. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
  144. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  145. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  146. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  147. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  148. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
  149. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
  150. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
  151. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
  152. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
  153. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
  154. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
  155. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
  156. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  157. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  158. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  159. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
  160. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  161. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  162. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  163. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  164. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
  165. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
  166. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
  167. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
  168. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
  169. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
  170. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
  171. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
  172. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
  173. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  174. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  175. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  176. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  177. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  178. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  179. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  180. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
  181. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
  182. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
  183. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/index.rst +0 -0
  184. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/index.rst +0 -0
  185. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/install.rst +0 -0
  186. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references/index.rst +0 -0
  187. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references/mol2-reference.pdf +0 -0
  188. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references.bib +0 -0
  189. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/release-history.rst +0 -0
  190. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/CURE.odg +0 -0
  191. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/bond_filter.odg +0 -0
  192. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
  193. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  194. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configuration-files.rst +0 -0
  195. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/container-usage.rst +0 -0
  196. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1.odg +0 -0
  197. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1yaml.odg +0 -0
  198. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.eps +0 -0
  199. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.fig +0 -0
  200. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
  201. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STY.png +0 -0
  202. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STYCC.png +0 -0
  203. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  204. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/bond_filter.png +0 -0
  205. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  206. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  207. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  208. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  209. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  210. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/postcure-repair.rst +0 -0
  211. {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/program-flow.rst +0 -0
  212. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/check-conda-sync.py +0 -0
  213. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/release.sh +0 -0
  214. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-detail.sh +0 -0
  215. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-detail.tcl +0 -0
  216. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-snapshot.sh +0 -0
  217. {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/run_all_examples.sh +0 -0
  218. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/__init__.py +0 -0
  219. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/__init__.py +0 -0
  220. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/plot.py +0 -0
  221. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/utils.py +0 -0
  222. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/__init__.py +0 -0
  223. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/bondtemplate.py +0 -0
  224. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/configuration.py +0 -0
  225. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/coordinates.py +0 -0
  226. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/topocoord.py +0 -0
  227. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/topology.py +0 -0
  228. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/__init__.py +0 -0
  229. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/chain.py +0 -0
  230. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/curecontroller.py +0 -0
  231. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/expandreactions.py +0 -0
  232. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/reaction.py +0 -0
  233. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/__init__.py +0 -0
  234. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/command.py +0 -0
  235. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/gromacs.py +0 -0
  236. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/slurm.py +0 -0
  237. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/smiles_input.py +0 -0
  238. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/__init__.py +0 -0
  239. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/bondlist.py +0 -0
  240. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/lattice.py +0 -0
  241. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/linkcell.py +0 -0
  242. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/matrix4.py +0 -0
  243. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/ring.py +0 -0
  244. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/__init__.py +0 -0
  245. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/gro.py +0 -0
  246. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/mol2.py +0 -0
  247. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/pdb.py +0 -0
  248. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/__init__.py +0 -0
  249. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/cyanate_cap.py +0 -0
  250. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/topology_surgery.py +0 -0
  251. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/README.md +0 -0
  252. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/__init__.py +0 -0
  253. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
  254. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
  255. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
  256. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
  257. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
  258. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
  259. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
  260. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/README.md +0 -0
  261. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  262. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  263. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  264. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/min.mdp +0 -0
  265. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  266. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  267. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  268. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  269. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  270. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  271. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  272. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  273. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  274. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  275. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  276. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  277. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  278. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
  279. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  280. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  281. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  282. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  283. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  284. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  285. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  286. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  287. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  288. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
  289. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  290. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  291. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  292. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
  293. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
  294. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  295. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  296. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/render.tcl +0 -0
  297. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/__init__.py +0 -0
  298. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/banner.py +0 -0
  299. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/checkpoint.py +0 -0
  300. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/dataframetools.py +0 -0
  301. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/inputcheck.py +0 -0
  302. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/logsetup.py +0 -0
  303. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/profiling.py +0 -0
  304. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/stringthings.py +0 -0
  305. {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/vmd_viz.py +0 -0
  306. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/__init__.py +0 -0
  307. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/conftest.py +0 -0
  308. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/__init__.py +0 -0
  309. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.gro +0 -0
  310. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.top +0 -0
  311. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.gro +0 -0
  312. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.top +0 -0
  313. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items31.edr +0 -0
  314. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items43.edr +0 -0
  315. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items45.edr +0 -0
  316. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/short.mdp +0 -0
  317. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_bondtemplate.py +0 -0
  318. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_chain.py +0 -0
  319. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_configuration.py +0 -0
  320. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_dataframetools.py +0 -0
  321. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gpu_usability.py +0 -0
  322. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
  323. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
  324. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_inputcheck.py +0 -0
  325. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_linkcell_pierce.py +0 -0
  326. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_parameterize_react.py +0 -0
  327. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_plot_smoke.py +0 -0
  328. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_resources.py +0 -0
  329. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_ring.py +0 -0
  330. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_ring_pierce_figs.py +0 -0
  331. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_slurm_script.py +0 -0
  332. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_smiles_input.py +0 -0
  333. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_topology/test.top +0 -0
  334. {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_topology.py +0 -0
@@ -0,0 +1,71 @@
1
+ ---
2
+ name: htpolynet
3
+ description: Build crosslinked polymer systems with htpolynet — authoring a run configuration, parameterizing monomers, running a cure, and reading the results. Use when the task involves an htpolynet YAML config, the `htpolynet` command (run, input-check, gen-slurm-script, plots, postsim, analyze, make-viz), a monomer's active form or sacrificial hydrogens, a cure that stalls below its target conversion, or sizing an htpolynet build for a cluster.
4
+ ---
5
+
6
+ # Working with htpolynet
7
+
8
+ **Read `docs/source/user-guide/building-a-system.rst` first.** It is the
9
+ procedure, start to finish, and it is maintained alongside the code. This
10
+ file exists to route you there and to carry the few things that are easy to
11
+ get wrong before you get that far. Do not restate the docs here; when they
12
+ and this file disagree, the docs are right.
13
+
14
+ ## Start from an example, never from an empty file
15
+
16
+ `htpolynet fetch-example <n>` unpacks a working configuration. Pick the one
17
+ closest in **reaction topology** — chain growth, A2+B3 step growth,
18
+ cyclotrimerization — not the one closest in chemistry. Adapt it. Writing a
19
+ config from scratch is the slowest route and the one that produces silent
20
+ errors.
21
+
22
+ Run the example unmodified once before editing, to confirm the toolchain and
23
+ to get a known-good log to diff against.
24
+
25
+ ## Monomers are described in their active form
26
+
27
+ The most common conceptual error, and it produces a build that completes and
28
+ is wrong rather than one that fails. htpolynet conserves valence: bonding
29
+ atoms each give up a sacrificial hydrogen, so you describe the monomer with
30
+ its reactive sites already saturated. Styrene is described as ethylbenzene.
31
+ See `docs/source/user-guide/molecular-structure-inputs.rst`.
32
+
33
+ In SMILES bracket atoms the hydrogen count is explicit: `[C:1]` means *zero*
34
+ implicit hydrogens. For an sp³ carbon you almost always want `[CH2:1]` or
35
+ `[CH3:1]`. A wrong count usually surfaces much later as a missing GAFF angle
36
+ parameter in `tleap`.
37
+
38
+ ## Subcommand routing
39
+
40
+ | Intent | Command |
41
+ |---|---|
42
+ | Build a system | `htpolynet run <cfg>` |
43
+ | Size it before queueing | `htpolynet input-check <cfg>` |
44
+ | Stop after parameterization | `htpolynet run --param-only <cfg>` |
45
+ | Submit to a cluster | `htpolynet gen-slurm-script <cfg>` |
46
+ | Plot a finished build | `htpolynet plots build --proj <dir>` |
47
+ | Post-build MD / analysis | `htpolynet postsim`, `htpolynet analyze` |
48
+ | Rebuild VMD viz files | `htpolynet make-viz` |
49
+ | Report the environment | `htpolynet info` |
50
+
51
+ ## Non-obvious facts
52
+
53
+ - **The container image cannot use a GPU.** Its Gromacs is conda-forge,
54
+ built against OpenCL, which Gromacs no longer uses for NVIDIA devices.
55
+ Target CPU partitions; never suggest `--gres=gpu` or `--nv`.
56
+ - **Size core requests from `htpolynet input-check`**, which reports the
57
+ initial atom count.
58
+ - **A cure stalling below its target conversion** is usually a reaction
59
+ template that never matches — suspect `symmetry_equivalent_atoms` and
60
+ reactive-atom names before suspecting the chemistry.
61
+ - **Builds are not reproducible run to run.** There is no seed control, so
62
+ replicas come free but an exact rebuild does not. Record the commit.
63
+
64
+ ## Do not
65
+
66
+ - Do not write workarounds into this file. If the tool surprises a user in a
67
+ way that requires a ritual to avoid, that is a bug: fix it in code, or file
68
+ it in `ROADMAP.md` with enough context to act on later. A skill that
69
+ teaches people to route around a defect keeps the defect.
70
+ - Do not hand-roll a release, a version bump, or a `CHANGELOG` rotation; see
71
+ `CLAUDE.md`.
@@ -7,6 +7,155 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.3.1] - 2026-08-25
11
+
12
+ ### Fixed
13
+
14
+ - **`htpolynet postsim` and `htpolynet analyze` no longer die in a directory
15
+ without a `lib/`.** Both took `-lib` with a default of `'lib'`, but only
16
+ `htpolynet run` creates that tree, so the default value of a flag the user
17
+ never typed reached `UserLibrary` and tripped its existence assertion:
18
+ `AssertionError: lib is not a directory`, three seconds in. The documented
19
+ container invocation failed on it -- running `postsim` against a staged
20
+ directory holding only finished results, which is the normal shape of a
21
+ cluster workflow, where the cure ran somewhere else.
22
+
23
+ `-lib` now defaults to nothing for these two subcommands, and the
24
+ conventional `./lib` is used when it happens to be there. An explicitly
25
+ supplied `-lib` is still validated, so a typo fails loudly rather than
26
+ silently degrading to no library. The assertion message now names the flag
27
+ and the resolved path instead of echoing a bare `lib` the user never
28
+ supplied.
29
+
30
+ ### Changed
31
+
32
+ - Documented that **the density at the end of `postcure` is not an
33
+ equilibrated density**, in the `postcure` directive reference and at the
34
+ point in the example 6 tutorial where a reader would take a number off the
35
+ plot. A crosslinked network relaxes only above its glass transition, and
36
+ a postcure anneal peaking near *Tg* spends almost no time where the
37
+ network can move, so the plateau reports an under-relaxed structure
38
+ however long the plateau runs. Measured on four independent BPA builds:
39
+ the plateau gives 1.1712 +/- 0.0029 g/cm3 against 1.1983 +/- 0.0037 for
40
+ the same systems melted and slowly re-cooled -- 2.31% apart, with the
41
+ plateau 2.6-2.8% below experiment and the re-cooled value within 1%.
42
+ Nothing is computed incorrectly; the protocol simply does not equilibrate
43
+ what a reader would assume it does. The example's own anneal peak is
44
+ unchanged pending a test that raising it actually helps; see `ROADMAP.md`.
45
+
46
+ - `htpolynet info` no longer reports `HTPolyNet git commit: unknown` for an
47
+ installed copy. pip, conda and the published container have no `.git`
48
+ beside the package, so the lookup could never succeed and a build had no
49
+ way to identify its own code from inside itself -- the same question the
50
+ parameterization records answer for molecules. It now falls back to the
51
+ installed distribution version, which for a released install maps to a tag.
52
+
53
+ - The warnings about a cached parameterization with no provenance record
54
+ now say that the cached values are being **used**, not merely that they
55
+ could not be checked. The old wording ("cannot be checked against the
56
+ requested 'bcc' charge method") left the decisive fact implicit: the
57
+ build proceeds with whatever charges that entry holds. A user who
58
+ upgrades with an existing library, asks for `bcc` and measures `gas`
59
+ numbers would reasonably conclude the 2.3.0 cache guard does not work --
60
+ correct behavior is otherwise indistinguishable from the bug it replaced.
61
+ Both the per-molecule line and the stage-end block now state that the
62
+ build carries the cached charges, that they may not match the requested
63
+ method, and that this is expected for a pre-2.3 entry rather than a
64
+ failure. The same clarification is made in the user guide and the
65
+ `ambertools` directive reference.
66
+
67
+ ## [2.3.0] - 2026-08-23
68
+
69
+ ### Fixed
70
+
71
+ - **A cached parameterization is no longer reused for a run that asked for
72
+ different AmberTools directives.** `molecules/parameterized` is keyed on
73
+ molecule name alone, and nothing in that key reflected the charge method.
74
+ A configuration specifying `charge_method: bcc` therefore reused, without
75
+ warning, a `gas` parameterization checked into the user library under the
76
+ same residue name, logging only `Using cached parameterization for TAZ`.
77
+ Measured on a cyanate-ester triazine, the cached `gas` entry carries ring
78
+ C +0.1185 / N -0.2249 where a real `bcc` run gives +0.6539 / -0.7160 --
79
+ 5.5x on the charge of the crosslink node -- and the result was a network
80
+ built with `bcc` on one monomer and Gasteiger on another, with nothing in
81
+ the output recording it. The failure was silent and invalidated results
82
+ without failing the build.
83
+
84
+ Each parameterization now writes a `.parm` record beside its
85
+ gro/top/itp/tpx/grx files listing the `charge_method`, `net_charge` and
86
+ `atom_type` that produced it, and that record is checked into the library
87
+ with them. A run whose directives disagree with the record treats the
88
+ cache as a miss and re-parameterizes, saying which directives differed.
89
+
90
+ A library entry written before this release carries no record. Those are
91
+ still used -- an existing library keeps working rather than
92
+ re-parameterizing wholesale -- but each one logs a warning naming the
93
+ charge method that could not be verified, and the parameterization stage
94
+ ends with a block listing every such molecule and the count. Rebuild them
95
+ with `--force-parameterization` if you need certainty about what a build
96
+ used.
97
+
98
+ Re-parameterizing after a mismatch checks its output in only under
99
+ `--force-checkin`, so a library entry is never silently replaced by one
100
+ built with different directives.
101
+
102
+ ### Added
103
+
104
+ - `ambertools.net_charge` and `ambertools.atom_type` configuration
105
+ directives, defaulting to `0` and `gaff`. The net charge was previously
106
+ hardcoded as `-nc 0` in the antechamber invocation, so an ionic or
107
+ zwitterionic monomer was parameterized as though it were neutral with no
108
+ way to say otherwise. The defaults reproduce the previous commands
109
+ exactly.
110
+
111
+ - A procedural page in the user guide, **Building a System, Start to
112
+ Finish**. The guide was strong on reference and had nothing on order of
113
+ operations: start from the nearest bundled example rather than an empty
114
+ file, describe monomers in their active form, check what you can before
115
+ spending compute, and a short list of failures that are known rather than
116
+ mysterious. It states plainly what `input-check` does not yet verify and
117
+ that there is no seed control, so builds are not reproducible run to run.
118
+
119
+ - A Claude skill (`.claude/skills/htpolynet/`) for users working in a clone
120
+ of the repository. It routes to the guide rather than restating it, and
121
+ carries the subcommand table and the handful of facts that are easy to get
122
+ wrong early.
123
+
124
+ - Test coverage for the parameterization record: 34 tests comparing records
125
+ without external tools, and 6 that run antechamber under both charge
126
+ methods to confirm the record describes what actually ran, that the
127
+ directive it guards changes the charges, and that a library holding a
128
+ `gas` entry refuses a `bcc` request while still reusing it for a `gas`
129
+ one. The latter skip when the AmberTools chain is absent.
130
+
131
+ ### Changed
132
+
133
+ - The `-lib` description in the user guide corrected. It said htpolynet
134
+ would "check-in the results of parameterized molecules ... in
135
+ `lib/molecules/parameterized`", which is false: `-lib` governs lookup
136
+ only, and check-in always goes to the per-user cache at `~/.htpolynet`
137
+ (or `$HTPOLYNET_CACHE`). A user who set `-lib` expecting to contain a
138
+ run's output was not contained, and nothing announced the writes.
139
+ `HTPOLYNET_CACHE` is now documented as the variable that actually governs
140
+ where products land.
141
+
142
+ - The user guide's "Parameterization caching" section corrected to match the
143
+ new behavior. It stated that a stale entry is silently reused when you
144
+ change "SMILES, atom-naming, or charge method" and that the cache is
145
+ "keyed by molecule name only"; the charge-method half of the first and all
146
+ of the second are no longer true. The warning now covers exactly what the
147
+ record does not: a constituent's structure, atom-naming or geometry
148
+ changing without a rename.
149
+
150
+ - `--force-checkin`'s help text corrected. It said "force check-in of
151
+ generated parameter files to the system library", which reads as though
152
+ check-in happens only when the flag is given. It does not: a molecule
153
+ whose name the library does not yet hold is checked in either way, and the
154
+ flag governs only whether an entry already there is *overwritten*. It
155
+ also named the wrong library -- check-in goes to the per-user library at
156
+ `~/.htpolynet` (or `$HTPOLYNET_CACHE`), not the system library. Behavior
157
+ is unchanged.
158
+
10
159
  ## [2.2.0] - 2026-08-23
11
160
 
12
161
  ### Changed
@@ -18,6 +18,12 @@ authors:
18
18
  email: cfa22@drexel.edu
19
19
  affiliation: Drexel University
20
20
  repository-code: https://github.com/cameronabrams/htpolynet
21
+ identifiers:
22
+ - type: doi
23
+ value: 10.5281/zenodo.22070252
24
+ description: >-
25
+ Concept DOI for htpolynet; always resolves to the latest
26
+ archived release.
21
27
  url: https://htpolynet.readthedocs.io/
22
28
  license: MIT
23
29
  version: 2.1.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: htpolynet
3
- Version: 2.2.0
3
+ Version: 2.3.1
4
4
  Summary: Automated MD System Builder for Amorphous Network Polymers
5
5
  Project-URL: Source, https://github.com/cameronabrams/htpolynet
6
6
  Project-URL: Documentation, https://htpolynet.readthedocs.io/
@@ -42,6 +42,7 @@ Description-Content-Type: text/markdown
42
42
  [![License: MIT](https://img.shields.io/pypi/l/htpolynet)](https://github.com/cameronabrams/htpolynet/blob/main/LICENSE)
43
43
  [![Docs](https://readthedocs.org/projects/htpolynet/badge/?version=latest)](https://htpolynet.readthedocs.io/en/latest/)
44
44
  [![PyPI Downloads](https://static.pepy.tech/badge/htpolynet)](https://pepy.tech/projects/htpolynet)
45
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22070252-blue)](https://doi.org/10.5281/zenodo.22070252)
45
46
 
46
47
  htpolynet is a Python utility for generating atomistic models of cross-linked polymer networks together with appropriate topology and parameter files required for molecular dynamics simulations using Gromacs. It is intended as a fully automated system builder requiring as inputs only the molecular structures of any monomer species, a description of the polymerization chemistry, and a handful of options describing desired system size and composition. htpolynet uses the Generalized Amber Force Field for atom-typing and parameter generation.
47
48
 
@@ -8,6 +8,7 @@
8
8
  [![License: MIT](https://img.shields.io/pypi/l/htpolynet)](https://github.com/cameronabrams/htpolynet/blob/main/LICENSE)
9
9
  [![Docs](https://readthedocs.org/projects/htpolynet/badge/?version=latest)](https://htpolynet.readthedocs.io/en/latest/)
10
10
  [![PyPI Downloads](https://static.pepy.tech/badge/htpolynet)](https://pepy.tech/projects/htpolynet)
11
+ [![DOI](https://img.shields.io/badge/DOI-10.5281%2Fzenodo.22070252-blue)](https://doi.org/10.5281/zenodo.22070252)
11
12
 
12
13
  htpolynet is a Python utility for generating atomistic models of cross-linked polymer networks together with appropriate topology and parameter files required for molecular dynamics simulations using Gromacs. It is intended as a fully automated system builder requiring as inputs only the molecular structures of any monomer species, a description of the polymerization chemistry, and a handful of options describing desired system size and composition. htpolynet uses the Generalized Amber Force Field for atom-typing and parameter generation.
13
14
 
@@ -0,0 +1,373 @@
1
+ # Roadmap
2
+
3
+ Ideas worth doing that we haven't done yet. This is a living list, not a
4
+ commitment or a schedule. When something here gets done, it moves to
5
+ `CHANGELOG.md` and comes off this page.
6
+
7
+ Rough ordering within each section is by value, not by effort.
8
+
9
+ ## Container and deployment
10
+
11
+ - **CUDA-enabled Gromacs in the container image.** The published image
12
+ installs Gromacs from conda-forge, whose default linux-64 package is
13
+ built with OpenCL (not CUDA) and generic `AVX2_256` SIMD. Gromacs no
14
+ longer drives NVIDIA devices through OpenCL, so the image cannot use a
15
+ GPU at all, and on an AVX-512 host it also leaves single-core
16
+ throughput on the table. For reference, Picotte's own module is
17
+ `AVX_512` + CUDA. Doing this well probably means a second image tag
18
+ (e.g. `:cuda`) built against `gromacs=*=nompi_cuda*` rather than
19
+ changing the default, since it pulls in the CUDA runtime and inflates
20
+ the image substantially, and it needs a GPU-equipped runner or a
21
+ manual build to verify. The CPU image should stay the default so that
22
+ `docker run` on a laptop keeps working. Note that
23
+ `software.gpu_unusable_reasons()` already reasons about this correctly,
24
+ so a CUDA image would simply start passing its checks rather than
25
+ needing new logic.
26
+ - **Publish a digest or version tag people can pin.** `:latest` moves
27
+ every week via the scheduled rebuild, so a run recorded as "built with
28
+ the container" is not reproducible. Per-commit tags already exist;
29
+ what's missing is documenting that users should pin one.
30
+
31
+ - **The container cannot report which commit built it, and its version
32
+ string is actively misleading between releases.** `htpolynet info` used to
33
+ print `git commit: unknown` inside the image, because `_get_git_commit()`
34
+ runs `git rev-parse` against the installed package directory and no
35
+ installed copy has a `.git` beside it. That now falls back to the
36
+ installed distribution version, which is right for a pip or conda install
37
+ and *precisely wrong for the container*: the scheduled rebuild builds from
38
+ `main` HEAD, which can be many commits past the last tag, so the image
39
+ reports its `pyproject.toml` version honestly while running code that is
40
+ not that version.
41
+
42
+ This is live, not hypothetical. The 2026-08-24 03:54 scheduled build moved
43
+ `:latest` to an image built from `948c301` -- four commits past `v2.3.0`
44
+ -- and that image reports `installed version 2.3.0`. `:latest` is the
45
+ default thing a user pulls and the weekly cron is what keeps moving it, so
46
+ the wrong answer is the common case, and it is wrong silently. A user
47
+ could pull `:latest`, trust the version string, and write "htpolynet
48
+ 2.3.0" in a methods section while having run untagged `main`.
49
+
50
+ The fix is to bake the real commit in at image build time -- the build
51
+ context has `.git`, so `docker.yml` or the Dockerfile can capture
52
+ `git rev-parse HEAD` and write it where the package can read it. That
53
+ touches the Dockerfile and the release story together, which is why it was
54
+ kept out of the bugfix that added the version fallback. It belongs with
55
+ the build-manifest entry below: both answer "what produced this build",
56
+ and a manifest that recorded an unreliable version string would launder
57
+ the problem rather than solve it. Raised by the calibration study, which
58
+ has correct provenance only because it pins the image by full sha
59
+ externally -- which remains the right practice either way.
60
+ - **Retire `ghcr.io/abramsgroup/htpolynet`.** Superseded by the
61
+ `cameronabrams` package; still public and still serving a June image to
62
+ anyone with an old link.
63
+
64
+ ## Testing and CI
65
+
66
+ Coverage as of the last measurement: **38.8%** overall.
67
+
68
+ - **`repair/` has no tests at all** — `cyanate_cap.py` (208 statements)
69
+ and `topology_surgery.py` (125), both at 0%. This is the highest-value
70
+ gap: the postcure repair stage makes the strongest correctness claim in
71
+ the project ("atom conservation is exact"), and right now the only
72
+ thing checking it is reading a residue census at the end of a
73
+ multi-hour build. It is pure topology manipulation, so it can be tested
74
+ deterministically in milliseconds against a synthetic `TopoCoord`
75
+ carrying triazines at k=0,1,2,3 — assert atom counts, the residue
76
+ census, cap placement, and that no unreacted bridge -OH survives.
77
+ - **An end-to-end example in CI.** A deliberately tiny build (a
78
+ 20-molecule, few-ps variant of example 0) run inside the container
79
+ would cover `core/runtime.py` and `cure/curecontroller.py` — 1,056
80
+ statements, both at 0% — in the only way that is honest, since faking
81
+ the whole AmberTools/Gromacs tool chain to unit-test the orchestration
82
+ is a large effort for less confidence.
83
+ - **Remaining zero-coverage modules**: `analysis/postsim.py` (203),
84
+ `cli.py` (165), `analysis/analyze.py` (137), `utils/vmd_viz.py` (75),
85
+ `utils/checkpoint.py` (54).
86
+ - **`analysis/plot.py` is at 34%** after the smoke-test pass. The
87
+ diagnostics-log parsers (`diagnostics_graphs`, `_token_match`,
88
+ `_parse_data`) are the part most likely to rot silently — they already
89
+ broke once when modules were renamed — and they are testable against a
90
+ small captured log fixture.
91
+ - **Coverage reporting in CI**, so the number is visible on a PR rather
92
+ than something we remember to measure by hand.
93
+
94
+ ## Release and distribution
95
+
96
+ - **External services still keyed to the old repo identity.** The Aug 2026
97
+ transfer from `AbramsGroup/HTPolyNet` to `cameronabrams/htpolynet` moved
98
+ the code but left every integration pointing at the old owner. Three
99
+ broke and were fixed during the 2.2.0 release: the GHCR package path
100
+ (docs referenced a package that had never been published under the new
101
+ owner), PyPI trusted publishing (`invalid-publisher` — the claim no
102
+ longer matched, so the v2.2.0 upload failed until the publisher was
103
+ re-registered), and Read the Docs, whose project `repository.url` is
104
+ **still** `https://github.com/AbramsGroup/htpolynet`. Builds succeed
105
+ anyway because GitHub redirects the clone, but tag versions never sync —
106
+ `/en/v2.2.0/` 404s and the API reports "No Version matches the given
107
+ query". Fix the RTD project URL, then activate the tagged version. Worth
108
+ keeping this list as the checklist if the repo ever moves again.
109
+
110
+
111
+ - **Mint a software DOI.** Enable the Zenodo GitHub integration for
112
+ `cameronabrams/htpolynet`, then the next `scripts/release.sh` run
113
+ archives the release automatically. Afterwards, add the concept DOI (not
114
+ the version DOI) as a README badge and an `identifiers` entry in
115
+ `CITATION.cff`. Note that enabling is not retroactive: releases before
116
+ the toggle are not archived. Also note that adding a `.zenodo.json`
117
+ would make Zenodo ignore `CITATION.cff` entirely — only worth doing if
118
+ we need Zenodo-specific fields such as `grants` for funder linkage.
119
+ - **Per-minor Python classifiers.** `pyproject.toml` declares only
120
+ `Programming Language :: Python :: 3`, so the PyPI Python badge reads an
121
+ uninformative `python: 3`. Adding `:: 3.10` through `:: 3.13` would make
122
+ it read `3.10 | 3.11 | 3.12 | 3.13`, which CI already verifies at both
123
+ ends.
124
+
125
+ ## Usability
126
+
127
+ - **`gen-slurm-script` doesn't stage to scratch.** The emitted script
128
+ runs in the submit directory. A cure run does heavy small-file I/O
129
+ every iteration, so on a cluster whose home and group storage are NFS
130
+ that is the wrong place. The cluster-correct pattern is to run in
131
+ node-local or parallel scratch and copy results back, with a `trap` so
132
+ partial results survive a timeout. It also cannot emit a job array,
133
+ which is the right shape for sweeping a set of configs.
134
+ - **`-restart` is documented as "EXPERIMENTAL: broken at the cure
135
+ stage".** A build that dies mid-cure currently has to start over — the
136
+ worst possible time to lose work, since cure is the longest stage.
137
+ - **Make `input-check` a real config linter.** It currently reports only
138
+ the initial atom count. Everything a new config gets wrong is checkable
139
+ cheaply and statically, before the user spends hours discovering it:
140
+ (a) that each `symmetry_equivalent_atoms` group really is topologically
141
+ equivalent — RDKit canonical ranks with `breakTies=False` settle it in
142
+ about ten lines, and a wrong group silently generates reaction templates
143
+ the cure stage will never match; (b) that the A2+B3 site counts actually
144
+ balance at the given monomer `count`s, and that `desired_conversion` is
145
+ reachable given them; (c) that no `reactive_atoms` name collides with the
146
+ bare element names `_reset_names_to_element` assigns to every unmapped
147
+ atom, since the repair stage looks atoms up by name; (d) that the
148
+ requested `charge_method` matches the provenance record of any cached
149
+ parameterization of the same name -- the build itself now rejects a
150
+ mismatch, but reporting it in the pre-flight is cheaper than discovering
151
+ mid-run that half the molecules need re-parameterizing. Building the
152
+ cyanate-ester bridge series meant doing (a) and (b) by hand in a throwaway
153
+ RDKit script, which is exactly the work a user should not have to
154
+ reinvent.
155
+ - **The bundled Claude skill only reaches people working in a clone.**
156
+ `.claude/skills/htpolynet/` is picked up when the working directory is the
157
+ repository, which covers contributors and anyone who cloned to run the
158
+ examples -- but not the ordinary user who `pip install`s or
159
+ `conda install`s htpolynet and works in their own project directory, which
160
+ is most of them. Whether to ship it inside the package is undecided.
161
+
162
+ Two things to settle before doing so, neither obvious:
163
+
164
+ 1. **The skill would be broken as written.** Its central move is "read
165
+ `docs/source/user-guide/building-a-system.rst`", a repo path that does
166
+ not exist for an installed user. A shipped version would have to point
167
+ at the Read the Docs URL instead, or the guide would have to ship as
168
+ package data. The first is simpler and goes stale differently -- an RTD
169
+ link tracks `latest`, so an installed 2.3.0 would send its reader to
170
+ documentation for whatever is current.
171
+ 2. **Delivery.** A skill file inside a wheel does nothing on its own;
172
+ something has to place it where the tool looks. An `htpolynet skill
173
+ --install` subcommand copying it into the user's `~/.claude/skills/`
174
+ is the obvious mechanism, and is also the point at which a scientific
175
+ package starts carrying vendor-specific tooling and an install-time
176
+ side effect on a directory it does not own.
177
+
178
+ Worth weighing against simply doing nothing: the procedural guide the skill
179
+ points at is on Read the Docs already, and an agent that reads
180
+ documentation gets the same content without any of this.
181
+
182
+ - **Generated topologies cannot be compared byte-wise, because ParmEd
183
+ stamps them.** Every `.top` htpolynet writes opens with a ParmEd header
184
+ recording the invoking user, the host, and the date:
185
+
186
+ ; File TAZ.top was generated
187
+ ; By user: cfa (1000)
188
+ ; On host: panacea.chemeng.drexel.edu
189
+ ; At date: Fri. May 5 15:55:38 2026
190
+
191
+ So two physically identical parameterizations never hash the same, and the
192
+ obvious check -- "did these two builds produce the same parameters for the
193
+ shared monomers?" -- returns a false difference. The calibration study hit
194
+ this on its bridge series and nearly reported the series confounded on the
195
+ strength of an md5; the fix on their side was to strip comment lines before
196
+ comparing, which every user will have to reinvent. Note the header is
197
+ itself provenance, but the wrong kind: it records *when and where* rather
198
+ than *what directives*, which is what the `parm` record now covers, and it
199
+ actively prevents the comparison you would want. The `.itp` files carry no
200
+ such header and the `parm` records are JSON with sorted keys, so both
201
+ already compare cleanly. Worth either normalizing the `.top` header away or
202
+ shipping a comparison helper; this belongs with the manifest entry below,
203
+ since both are about being able to answer "is this the same build?".
204
+
205
+ - **`-lib` is read-only, and nothing says so.** `pfs.checkout()` and
206
+ `pfs.exists()` consult the `-lib` user library first, then the user cache,
207
+ then the system library -- but `pfs.checkin()` writes unconditionally to the
208
+ user cache, and `UserLibrary` has no `checkin()` method at all. So pointing
209
+ a run at `-lib somewhere` redirects where it *reads* parameterizations from
210
+ while leaving where it *writes* them untouched. That asymmetry is invisible
211
+ from the flag, from `--help`, and from the docs, and it is a natural thing
212
+ to get wrong: a user who passes `-lib` for provenance reasonably concludes
213
+ their products are being contained there. Either `checkin()` should prefer
214
+ the user library when one is configured, or the flag and docs should say
215
+ plainly that it governs lookup only. Verified empirically 2026-08-23: with
216
+ `userlibrary` set, `pfs.checkin()` still landed the file in the user cache.
217
+
218
+ What makes this more than a naming problem is that the writes are silent
219
+ and cumulative. Nothing logs them, nothing warns, and a run that is
220
+ quietly depositing molecules into a shared library looks identical to one
221
+ that is not -- the only way to discover it is to audit mtimes, which
222
+ nobody does unprompted. The calibration study ran three sweeps believing
223
+ `-lib` contained it, and would have added roughly seventy entries to
224
+ `~/.htpolynet` across its remaining bridges; it was caught by reading
225
+ `checkin()`, not by anything the tool said. Whatever the fix, a run should
226
+ be able to say where its parameterizations went -- which is the same
227
+ requirement as the build manifest below, approached from the write side
228
+ rather than the read side. The two may well be one item: *where did this
229
+ come from, and what produced it*.
230
+
231
+ - **No way to run without writing to the user library.** `pfs.checkin()`
232
+ declines to *replace* an entry unless `--force-checkin` is given, but it
233
+ always *writes* one the library does not yet hold, so any run adds every
234
+ molecule name it produces to `~/.htpolynet`. The flag's help text said
235
+ "force check-in of generated parameter files to the system library", which
236
+ reads as though check-in happens only with the flag, and it named the wrong
237
+ library; that wording is fixed, but the missing capability is real. The
238
+ calibration study wanted exactly this: a way to develop against a config
239
+ without its intermediate products accumulating in a library shared with
240
+ other work. Today the only lever is pointing `HTPOLYNET_CACHE` elsewhere,
241
+ which is a blunt instrument because it also hides the entries you *do* want
242
+ to reuse. A `--no-checkin` flag threaded through
243
+ `Runtime._checkin_parameterization()` would cover it in a few lines.
244
+
245
+ - **Two different defaults for `charge_method`.** `AMBERTOOLS_DEFAULTS` in
246
+ `external/ambertools.py` says `bcc`, which is what a direct
247
+ `GAFFParameterize()` call with no directives gets; `Runtime.runtime_defaults`
248
+ says `gas`, which is what every actual build gets, because
249
+ `_apply_runtime_defaults()` fills it in before AmberTools is ever reached.
250
+ Both were already there and the provenance record is consistent either way
251
+ -- whichever default applies is the one recorded -- so this is a
252
+ readability trap rather than a live bug. It is still worth collapsing to
253
+ one value, and the answer is probably `gas`, since changing what builds
254
+ default to would silently change everyone's charges, which is the exact
255
+ class of harm the record was added to prevent.
256
+
257
+ - **Nothing durable records that a build reused parameterizations of
258
+ unverified provenance.** The parameterization stage now warns per molecule
259
+ and again in a block at the end of the stage, but both live only in the
260
+ log, and a log is the first thing discarded. Someone reading a result six
261
+ months later -- or a reviewer asking what a published network was actually
262
+ parameterized with -- has no artifact to check. htpolynet writes no build
263
+ manifest today; `profile.json` holds timings only, and the diagnostic log
264
+ is the log. A small `build-manifest.json` in the project directory listing
265
+ each molecule, its origin (`newly parameterized` / `previously
266
+ parameterized`), and its provenance record where one exists would carry
267
+ that, and would be worth more than this one flag: it is also the natural
268
+ home for the config hash, the htpolynet and AmberTools versions, and the
269
+ seed once seeds exist. Raised by the calibration study, which caught the
270
+ original cache bug from a wall-clock anomaly rather than from any log line.
271
+ See also the `-lib` entry above: "a run should be able to say where its
272
+ parameterizations went" and "a result should be able to say what produced
273
+ it" are the same requirement from two directions, and a manifest that
274
+ recorded the check-in destination would answer both.
275
+
276
+ - **A cached parameterization is not checked against the input structure
277
+ it was built from.** The provenance record added alongside the cache now
278
+ covers `charge_method`, `net_charge` and `atom_type` -- everything in the
279
+ AmberTools invocation -- but not the structure antechamber consumed. So
280
+ editing `lib/molecules/inputs/TAZ.mol2` and re-running still reuses the
281
+ parameterization of the *old* geometry, silently, exactly as the charge
282
+ method used to. Hashing the input would close it, and for a monomer that
283
+ is easy: `Molecule.parameterize()` has the input file in the working
284
+ directory at the moment it runs. Two things stopped it going in with the
285
+ rest: (a) a molecule built by a reaction has no stable input to hash --
286
+ `generate()` writes its mol2 from the merged reactant TopoCoord, whose
287
+ coordinates vary run to run, so hashing it would make every generated
288
+ molecule a permanent cache miss; the hash would have to be recorded only
289
+ for `origin == 'unparameterized'` monomers and compared only when both
290
+ sides carry one. (b) `Runtime._cached_parameterization_mismatch()` runs
291
+ before `generate()` checks the input structure out, and `pfs` has no way
292
+ to resolve a library file to an absolute path without copying it into the
293
+ working directory -- `checkout()` always copies. A `pfs.locate(filename)`
294
+ returning the resolved source path across user library, user cache and
295
+ system library is the missing piece, and is worth having on its own.
296
+
297
+ - **No seed control anywhere, so a build cannot be reproduced.** Three
298
+ independent sources of randomness are all unseeded: `random.sample` for
299
+ conformer selection (`core/runtime.py`), `np.random.random()` for the
300
+ per-bond probability test (`cure/curecontroller.py`), and every `.mdp`
301
+ sets `gen-vel = yes` without `gen-seed`, so Gromacs picks a pseudo-random
302
+ one per run. Two runs of one config therefore diverge — example 6 gave 57
303
+ vs 60 incomplete triazines on two machines at the same 0.90 conversion.
304
+ That is convenient in one direction (independent replicas of a
305
+ quenched-disorder ensemble come free by re-running) but it means a build
306
+ reported in a paper cannot be reproduced exactly, and a failure seen once
307
+ may not reappear. The fix is a top-level `seed:` that feeds all three:
308
+ seed `random` and `np.random` at startup and write `gen-seed` into every
309
+ generated mdp, with replicas then requested by varying it rather than by
310
+ relying on entropy.
311
+ - **Drop the pre-3.5 matplotlib fallback** in `analysis/plot.py`'s
312
+ `_get_cmap()` once `matplotlib>=3.6` is a safe floor; the
313
+ `matplotlib.colormaps` registry is then always present.
314
+
315
+ ## Example depot
316
+
317
+ - **Example 6's postcure anneal peaks too close to *T*:sub:`g` to relax the
318
+ network, and the fix is not simply "run it longer".** Measured on four
319
+ independent BPA builds: the postcure NPT plateau gives 1.1712 ± 0.0029
320
+ g/cm³ where the same systems melted and slowly re-cooled give 1.1983 ±
321
+ 0.0037 g/cm³ -- 2.31% apart, with the plateau 2.6-2.8% below experiment
322
+ and the re-cooled value within 1%. The plateau is an under-relaxed
323
+ structure.
324
+
325
+ The mechanism, and the reason the obvious fix is the wrong one: the
326
+ example anneals at a 500 K peak, and the measured *T*:sub:`g` for this
327
+ system is 487.9 K. That is 12.1 K above the glass transition, for 80 ps.
328
+ The Tg ladder that produced the relaxed value spent 15,785 ps above
329
+ *T*:sub:`g`, peaking 112 K above it -- 197x the time, in the only regime
330
+ where a crosslinked network moves at all. Lengthening an anneal that sits
331
+ 12 K above *T*:sub:`g` extends a process that barely moves anything, so
332
+ the lever is the peak temperature, not the duration.
333
+
334
+ **Untested.** Nobody has yet built with a hotter anneal and compared it
335
+ against the melt-and-recool value, which is the experiment that would
336
+ settle it; the argument above is mechanism, not measurement. That is why
337
+ the example is documented rather than changed. Raising the peak also costs
338
+ wall-clock in a tutorial that should stay small, so the test needs to
339
+ report both whether it works and what it costs.
340
+
341
+ The general problem is worth more than the instance: **any protocol whose
342
+ relaxation depends on being above *T*:sub:`g` is fragile when *T*:sub:`g`
343
+ is unknown at configuration time**, which it always is -- you cannot know
344
+ it before building the thing. A fixed absolute peak temperature is a guess
345
+ that happens to be right or wrong per chemistry, silently. Something
346
+ expressed relative to an estimated or measured *T*:sub:`g`, or a postcure
347
+ that measures *T*:sub:`g` and then anneals accordingly, would be robust
348
+ where an absolute number is not. That is a real design change, not a
349
+ config edit.
350
+
351
+ Raised by the calibration study, which had already published the
352
+ pessimistic density before catching it -- the failure mode is reporting a
353
+ protocol artifact as a force-field result.
354
+
355
+ - **Example 5 is still not laptop-scale.** The `68d81fb` retune cut the
356
+ monomer pool to make HTPB/IPDI "fit in a reasonable wall time on a
357
+ laptop", but a validation run on 16 CPU cores took **10h17m** — about
358
+ ten times any other example (the next longest, PACM/DGEBA, was 2h15m).
359
+ The cost is structural: densification starts at 10 kg/m³ in a 27 nm box
360
+ and needs all 50 NPT repeats to compress geometrically (a steady 2.9%
361
+ box-side reduction per repeat) up to ~860 kg/m³, and the cure stage then
362
+ does drag/relax on long chains. Worth revisiting whether the low
363
+ starting density is really necessary, or whether the example can start
364
+ denser with a shorter densification.
365
+
366
+
367
+ - **More cyanate-ester variants.** Example 6 covers bisphenol-A
368
+ dicyanate. The same reaction and repair machinery carries over to other
369
+ bisphenol bridges with only a SMILES swap in `constituents` — bisphenol
370
+ F (methylene), bisphenol E (methylethylidene), hexafluorobisphenol A,
371
+ thioether, sulfone, dicyclopentadiene. A homologous series would
372
+ exercise the repair stage across chemistries and give the tutorials a
373
+ structure-property story.