htpolynet 2.0.1__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (393) hide show
  1. htpolynet-2.2.0/.envrc +4 -0
  2. htpolynet-2.2.0/.github/workflows/conda-forge-sync.yml +56 -0
  3. {htpolynet-2.0.1 → htpolynet-2.2.0}/.github/workflows/docker.yml +3 -2
  4. htpolynet-2.2.0/.github/workflows/test.yml +30 -0
  5. {htpolynet-2.0.1 → htpolynet-2.2.0}/.gitignore +4 -2
  6. htpolynet-2.2.0/CHANGELOG.md +303 -0
  7. htpolynet-2.2.0/CITATION.cff +50 -0
  8. htpolynet-2.2.0/CLAUDE.md +103 -0
  9. htpolynet-2.2.0/PKG-INFO +127 -0
  10. htpolynet-2.2.0/README.md +93 -0
  11. htpolynet-2.2.0/ROADMAP.md +116 -0
  12. htpolynet-2.2.0/docker/Dockerfile +66 -0
  13. htpolynet-2.2.0/docker/compose.yml +13 -0
  14. htpolynet-2.2.0/docker/docker-entrypoint.sh +36 -0
  15. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/requirements.txt +1 -0
  16. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/conf.py +2 -2
  17. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +60 -0
  18. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/index.rst +21 -0
  19. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +31 -0
  20. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +46 -0
  21. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +57 -0
  22. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/results.rst +44 -0
  23. htpolynet-2.2.0/docs/source/example-tutorials/0-liquid-styrene/run.rst +46 -0
  24. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/configuration.rst +67 -0
  25. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/index.rst +24 -0
  26. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/introduction.rst +34 -0
  27. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/monomer.rst +87 -0
  28. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  29. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  30. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  31. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  32. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  33. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +22 -0
  34. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  35. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  36. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  37. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/postsim.rst +102 -0
  38. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/reactions.rst +90 -0
  39. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/results.rst +95 -0
  40. htpolynet-2.2.0/docs/source/example-tutorials/1-polystyrene/run.rst +92 -0
  41. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +95 -0
  42. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +24 -0
  43. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +32 -0
  44. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  45. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  46. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  47. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +23 -0
  48. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  49. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  50. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  51. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  52. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +127 -0
  53. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +163 -0
  54. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +105 -0
  55. htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +152 -0
  56. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +93 -0
  57. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +34 -0
  58. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +36 -0
  59. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +89 -0
  60. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  61. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  62. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  63. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +26 -0
  64. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  65. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  66. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  67. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  68. htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses/index.rst → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +9 -6
  69. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +122 -0
  70. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +91 -0
  71. htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +140 -0
  72. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +72 -0
  73. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +37 -0
  74. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +37 -0
  75. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +86 -0
  76. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  77. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  78. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  79. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +27 -0
  80. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  81. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  82. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  83. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  84. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +127 -0
  85. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +97 -0
  86. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +157 -0
  87. htpolynet-2.2.0/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +54 -0
  88. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +97 -0
  89. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/index.rst +45 -0
  90. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +67 -0
  91. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +149 -0
  92. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  93. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  94. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  95. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +17 -0
  96. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  97. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  98. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  99. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  100. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +154 -0
  101. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +204 -0
  102. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/results.rst +145 -0
  103. htpolynet-2.2.0/docs/source/example-tutorials/5-htpb-ipdi/run.rst +197 -0
  104. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +120 -0
  105. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/index.rst +51 -0
  106. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +75 -0
  107. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +120 -0
  108. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +23 -0
  109. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  110. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  111. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  112. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  113. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  114. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  115. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  116. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +163 -0
  117. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +146 -0
  118. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/results.rst +142 -0
  119. htpolynet-2.2.0/docs/source/example-tutorials/6-cyanate-ester/run.rst +199 -0
  120. htpolynet-2.2.0/docs/source/example-tutorials/index.rst +24 -0
  121. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/htpolynetpackage.rst +49 -9
  122. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/index.rst +1 -0
  123. htpolynet-2.2.0/docs/source/install.rst +234 -0
  124. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/release-history.rst +1 -1
  125. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/configs/configs-for-run.rst +17 -8
  126. htpolynet-2.2.0/docs/source/user-guide/container-usage.rst +268 -0
  127. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/index.rst +1 -0
  128. htpolynet-2.2.0/docs/source/user-guide/molecular-structure-inputs.rst +76 -0
  129. htpolynet-2.2.0/docs/source/user-guide/postcure-repair.rst +313 -0
  130. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/program-flow.rst +57 -9
  131. htpolynet-2.2.0/docs/source/user-guide/usage.rst +475 -0
  132. {htpolynet-2.0.1 → htpolynet-2.2.0}/pyproject.toml +12 -5
  133. htpolynet-2.2.0/scripts/check-conda-sync.py +181 -0
  134. {htpolynet-2.0.1 → htpolynet-2.2.0}/scripts/release.sh +52 -2
  135. htpolynet-2.2.0/scripts/render-detail.sh +104 -0
  136. htpolynet-2.2.0/scripts/render-detail.tcl +207 -0
  137. htpolynet-2.2.0/scripts/render-snapshot.sh +200 -0
  138. htpolynet-2.2.0/scripts/run_all_examples.sh +164 -0
  139. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/analysis/plot.py +318 -119
  140. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/cli.py +29 -219
  141. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/bondtemplate.py +69 -0
  142. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/configuration.py +2 -0
  143. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/molecule.py +27 -10
  144. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/projectfilesystem.py +22 -7
  145. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/runtime.py +276 -79
  146. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/topocoord.py +60 -73
  147. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/topology.py +74 -3
  148. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/cure/chain.py +18 -6
  149. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/cure/curecontroller.py +17 -15
  150. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/cure/expandreactions.py +1 -1
  151. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/cure/reaction.py +8 -7
  152. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/external/ambertools.py +6 -1
  153. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/external/command.py +5 -0
  154. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/external/gromacs.py +5 -3
  155. htpolynet-2.2.0/src/htpolynet/external/smiles_input.py +261 -0
  156. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/external/software.py +66 -7
  157. htpolynet-2.2.0/src/htpolynet/repair/__init__.py +39 -0
  158. htpolynet-2.2.0/src/htpolynet/repair/cyanate_cap.py +409 -0
  159. htpolynet-2.2.0/src/htpolynet/repair/topology_surgery.py +256 -0
  160. htpolynet-2.2.0/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +81 -0
  161. htpolynet-2.0.1/src/htpolynet/resources/example_depot/1-polystyrene.sh → htpolynet-2.2.0/src/htpolynet/resources/example_depot/1-polystyrene.yaml +14 -49
  162. htpolynet-2.0.1/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.sh → htpolynet-2.2.0/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +23 -76
  163. htpolynet-2.0.1/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.sh → htpolynet-2.2.0/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +17 -67
  164. htpolynet-2.2.0/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +191 -0
  165. htpolynet-2.2.0/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +363 -0
  166. htpolynet-2.2.0/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +238 -0
  167. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/banner.py +1 -1
  168. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/inputcheck.py +2 -0
  169. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/logsetup.py +10 -4
  170. htpolynet-2.2.0/src/htpolynet/utils/profiling.py +219 -0
  171. htpolynet-2.2.0/src/htpolynet/utils/vmd_viz.py +288 -0
  172. htpolynet-2.2.0/tests/unit/__init__.py +0 -0
  173. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_chain.py +27 -16
  174. htpolynet-2.2.0/tests/unit/test_gpu_usability.py +77 -0
  175. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_gromacs_get_energy_menu.py +4 -0
  176. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_gromacs_gmx_energy_trace.py +4 -0
  177. htpolynet-2.2.0/tests/unit/test_inputcheck.py +112 -0
  178. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_parameterize_react.py +9 -0
  179. htpolynet-2.2.0/tests/unit/test_plot_smoke.py +143 -0
  180. htpolynet-2.2.0/tests/unit/test_resources.py +76 -0
  181. htpolynet-2.2.0/tests/unit/test_slurm_script.py +162 -0
  182. htpolynet-2.2.0/tests/unit/test_smiles_input.py +110 -0
  183. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_topology.py +9 -6
  184. htpolynet-2.0.1/CHANGELOG.md +0 -56
  185. htpolynet-2.0.1/Dockerfile +0 -45
  186. htpolynet-2.0.1/PKG-INFO +0 -78
  187. htpolynet-2.0.1/README.md +0 -50
  188. htpolynet-2.0.1/compose.yml +0 -7
  189. htpolynet-2.0.1/docs/source/example-tutorials/index.rst +0 -13
  190. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/configuration.rst +0 -164
  191. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/index.rst +0 -18
  192. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/introduction.rst +0 -38
  193. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/monomer.rst +0 -90
  194. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/reactions.rst +0 -70
  195. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/results.rst +0 -32
  196. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/run.rst +0 -48
  197. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/configuration.rst +0 -51
  198. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/index.rst +0 -16
  199. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/introduction.rst +0 -69
  200. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/monomers.rst +0 -295
  201. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/pics/buildtraces.png +0 -0
  202. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/pics/cure_info.png +0 -0
  203. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/pics/densification-density.png +0 -0
  204. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/pics/dge-pac-cured.png +0 -0
  205. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/pics/dge-pac-liq.png +0 -0
  206. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/reactions.rst +0 -104
  207. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/results.rst +0 -46
  208. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/run.rst +0 -267
  209. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/configuration.rst +0 -39
  210. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/index.rst +0 -15
  211. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/introduction.rst +0 -68
  212. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/pics/buildtraces.png +0 -0
  213. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/pics/cure_info.png +0 -0
  214. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/pics/densification-density.png +0 -0
  215. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/pics/gma-sty-cured.png +0 -0
  216. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/pics/gma-sty-liq.png +0 -0
  217. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/reactions.rst +0 -275
  218. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/results.rst +0 -46
  219. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY/run.rst +0 -374
  220. htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/index.rst +0 -18
  221. htpolynet-2.0.1/docs/source/install.rst +0 -131
  222. htpolynet-2.0.1/docs/source/user-guide/container-usage.rst +0 -143
  223. htpolynet-2.0.1/docs/source/user-guide/molecular-structure-inputs.rst +0 -35
  224. htpolynet-2.0.1/docs/source/user-guide/pics/CURE.png +0 -0
  225. htpolynet-2.0.1/docs/source/user-guide/pics/flow1.png +0 -0
  226. htpolynet-2.0.1/docs/source/user-guide/usage.rst +0 -271
  227. htpolynet-2.0.1/src/htpolynet/resources/cfg/DGE-PAC-hi.yaml +0 -115
  228. htpolynet-2.0.1/src/htpolynet/resources/cfg/DGE-PAC-lo.yaml +0 -115
  229. htpolynet-2.0.1/src/htpolynet/resources/cfg/FDE-DFDA-hi.yaml +0 -116
  230. htpolynet-2.0.1/src/htpolynet/resources/cfg/FDE-DFDA-lo.yaml +0 -116
  231. htpolynet-2.0.1/src/htpolynet/resources/cfg/GMASTY-hi.yaml +0 -158
  232. htpolynet-2.0.1/src/htpolynet/resources/cfg/GMASTY-lo.yaml +0 -158
  233. htpolynet-2.0.1/src/htpolynet/resources/cfg/README.md +0 -1
  234. htpolynet-2.0.1/src/htpolynet/resources/cfg/STY.yaml +0 -23
  235. htpolynet-2.0.1/src/htpolynet/resources/cfg/pMSTY-hi.yaml +0 -101
  236. htpolynet-2.0.1/src/htpolynet/resources/cfg/pMSTY-lo.yaml +0 -101
  237. htpolynet-2.0.1/src/htpolynet/resources/cfg/pSTY-hi.yaml +0 -101
  238. htpolynet-2.0.1/src/htpolynet/resources/cfg/pSTY-lo.yaml +0 -101
  239. htpolynet-2.0.1/src/htpolynet/resources/example_depot/0-liquid-styrene.sh +0 -134
  240. htpolynet-2.0.1/src/htpolynet/resources/example_depot/0-liquid-styrene.tgz +0 -0
  241. htpolynet-2.0.1/src/htpolynet/resources/example_depot/1-polystyrene.tgz +0 -0
  242. htpolynet-2.0.1/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.tgz +0 -0
  243. htpolynet-2.0.1/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.tgz +0 -0
  244. htpolynet-2.0.1/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.sh +0 -216
  245. htpolynet-2.0.1/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.tgz +0 -0
  246. htpolynet-2.0.1/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -115
  247. htpolynet-2.0.1/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -91
  248. htpolynet-2.0.1/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -44
  249. htpolynet-2.0.1/tests/unit/test_resources.py +0 -24
  250. {htpolynet-2.0.1 → htpolynet-2.2.0}/.claude/settings.json +0 -0
  251. {htpolynet-2.0.1 → htpolynet-2.2.0}/.github/workflows/release.yaml +0 -0
  252. {htpolynet-2.0.1 → htpolynet-2.2.0}/.readthedocs.yaml +0 -0
  253. {htpolynet-2.0.1 → htpolynet-2.2.0}/LICENSE +0 -0
  254. {htpolynet-2.0.1 → htpolynet-2.2.0}/MANIFEST.in +0 -0
  255. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/Makefile +0 -0
  256. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/README.rst +0 -0
  257. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/make.bat +0 -0
  258. /htpolynet-2.0.1/src/htpolynet/analysis/__init__.py → /htpolynet-2.2.0/docs/source/_static/.gitkeep +0 -0
  259. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/changelog.rst +0 -0
  260. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds → htpolynet-2.2.0/docs/source/example-tutorials}/1-polystyrene/pics/STY.png +0 -0
  261. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds → htpolynet-2.2.0/docs/source/example-tutorials}/1-polystyrene/pics/STYCC.png +0 -0
  262. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds → htpolynet-2.2.0/docs/source/example-tutorials}/1-polystyrene/pics/styrene-polymerization.png +0 -0
  263. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/BPA.png +0 -0
  264. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/GMA.png +0 -0
  265. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/HIE.png +0 -0
  266. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/four_dimers.eps +0 -0
  267. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/four_dimers.fig +0 -0
  268. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/four_dimers.png +0 -0
  269. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/p1-traces.png +0 -0
  270. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/vesys.eps +0 -0
  271. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/vesys.fig +0 -0
  272. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/3-VE-STY → htpolynet-2.2.0/docs/source/example-tutorials/2-bisgma-styrene-thermoset}/pics/vesys.png +0 -0
  273. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/DGE-epoxy.png +0 -0
  274. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/DGE-labelled.png +0 -0
  275. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/PAC-2d.png +0 -0
  276. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/PAC-labelled.png +0 -0
  277. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/dgesys.eps +0 -0
  278. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/dgesys.fig +0 -0
  279. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/dgesys.png +0 -0
  280. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/equil-rho_v_ns.png +0 -0
  281. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/postsim-typical.png +0 -0
  282. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/prod-e.png +0 -0
  283. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/prod-equil-rho_v_ns.png +0 -0
  284. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/prod-rho_v_ns.png +0 -0
  285. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/prod-tg.png +0 -0
  286. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/r1.png +0 -0
  287. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/r2.png +0 -0
  288. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/r3.png +0 -0
  289. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/rho_v_ns.png +0 -0
  290. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/short-e.png +0 -0
  291. {htpolynet-2.0.1/docs/source/example-tutorials/postsim_analyses → htpolynet-2.2.0/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset}/pics/short-tg.png +0 -0
  292. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/references/index.rst +0 -0
  293. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/references/mol2-reference.pdf +0 -0
  294. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/references.bib +0 -0
  295. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/CURE.odg +0 -0
  296. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/bond_filter.odg +0 -0
  297. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
  298. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  299. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/configuration-files.rst +0 -0
  300. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/flow1.odg +0 -0
  301. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/flow1yaml.odg +0 -0
  302. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/hydrogenated.eps +0 -0
  303. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/hydrogenated.fig +0 -0
  304. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/STY.png +0 -0
  305. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/STYCC.png +0 -0
  306. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  307. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
  308. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  309. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  310. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  311. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  312. {htpolynet-2.0.1 → htpolynet-2.2.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  313. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/__init__.py +0 -0
  314. {htpolynet-2.0.1/src/htpolynet/core → htpolynet-2.2.0/src/htpolynet/analysis}/__init__.py +0 -0
  315. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/analysis/analyze.py +0 -0
  316. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/analysis/postsim.py +0 -0
  317. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/analysis/utils.py +0 -0
  318. {htpolynet-2.0.1/src/htpolynet/cure → htpolynet-2.2.0/src/htpolynet/core}/__init__.py +0 -0
  319. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/core/coordinates.py +0 -0
  320. {htpolynet-2.0.1/src/htpolynet/external → htpolynet-2.2.0/src/htpolynet/cure}/__init__.py +0 -0
  321. {htpolynet-2.0.1/src/htpolynet/geometry → htpolynet-2.2.0/src/htpolynet/external}/__init__.py +0 -0
  322. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/external/slurm.py +0 -0
  323. {htpolynet-2.0.1/src/htpolynet/resources → htpolynet-2.2.0/src/htpolynet/geometry}/__init__.py +0 -0
  324. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/geometry/bondlist.py +0 -0
  325. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/geometry/lattice.py +0 -0
  326. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/geometry/linkcell.py +0 -0
  327. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/geometry/matrix4.py +0 -0
  328. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/geometry/ring.py +0 -0
  329. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/io/__init__.py +0 -0
  330. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/io/gro.py +0 -0
  331. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/io/mol2.py +0 -0
  332. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/io/pdb.py +0 -0
  333. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/README.md +0 -0
  334. {htpolynet-2.0.1/src/htpolynet/utils → htpolynet-2.2.0/src/htpolynet/resources}/__init__.py +0 -0
  335. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/README.md +0 -0
  336. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  337. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  338. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  339. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
  340. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  341. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  342. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  343. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  344. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  345. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  346. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  347. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  348. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  349. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  350. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  351. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  352. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  353. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/1-polystyrene/files → htpolynet-2.2.0/src/htpolynet/resources/molecules/inputs}/STY.mol2 +0 -0
  354. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  355. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  356. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  357. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  358. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  359. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  360. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  361. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  362. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  363. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/files → htpolynet-2.2.0/src/htpolynet/resources/molecules/sample-inputs}/DGE.mol2 +0 -0
  364. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  365. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  366. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  367. {htpolynet-2.0.1/docs/source/example-tutorials/shortbuilds/2-DGEBA-PACM/files → htpolynet-2.2.0/src/htpolynet/resources/molecules/sample-inputs}/PAC.mol2 +0 -0
  368. {htpolynet-2.0.1/src/htpolynet/resources/molecules/inputs → htpolynet-2.2.0/src/htpolynet/resources/molecules/sample-inputs}/STY.mol2 +0 -0
  369. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  370. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  371. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
  372. {htpolynet-2.0.1/tests → htpolynet-2.2.0/src/htpolynet/utils}/__init__.py +0 -0
  373. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/checkpoint.py +0 -0
  374. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/dataframetools.py +0 -0
  375. {htpolynet-2.0.1 → htpolynet-2.2.0}/src/htpolynet/utils/stringthings.py +0 -0
  376. {htpolynet-2.0.1/tests/unit → htpolynet-2.2.0/tests}/__init__.py +0 -0
  377. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/conftest.py +0 -0
  378. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/config1.gro +0 -0
  379. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/config1.top +0 -0
  380. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/config2.gro +0 -0
  381. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/config2.top +0 -0
  382. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/items31.edr +0 -0
  383. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/items43.edr +0 -0
  384. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/items45.edr +0 -0
  385. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/fixtures/short.mdp +0 -0
  386. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_bondtemplate.py +0 -0
  387. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_configuration.py +0 -0
  388. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_dataframetools.py +0 -0
  389. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_linkcell_pierce.py +0 -0
  390. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_projectfilesystem.py +0 -0
  391. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_ring.py +0 -0
  392. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_ring_pierce_figs.py +0 -0
  393. {htpolynet-2.0.1 → htpolynet-2.2.0}/tests/unit/test_topology/test.top +0 -0
htpolynet-2.2.0/.envrc ADDED
@@ -0,0 +1,4 @@
1
+ # direnv: auto-activate this repo's uv-managed virtualenv on `cd` in.
2
+ # Created with `uv venv .venv`. Run `direnv allow` once to trust this file.
3
+ export VIRTUAL_ENV="$PWD/.venv"
4
+ PATH_add "$VIRTUAL_ENV/bin"
@@ -0,0 +1,56 @@
1
+ # Check that pyproject.toml's runtime dependencies are in sync with
2
+ # the conda-forge feedstock's `requirements.run` block.
3
+ #
4
+ # Two modes:
5
+ # - Push/PR to main: warn-only. Drift adds a job-summary line so a
6
+ # reviewer notices but the workflow doesn't fail.
7
+ # - Tag push (v*): strict. Drift fails the job, so a release tag
8
+ # can't ship with a recipe known to be broken.
9
+ #
10
+ # The script that does the work is scripts/check-conda-sync.py; see
11
+ # its header for what gets compared and the PyPI→conda-forge name
12
+ # remap.
13
+
14
+ name: conda-forge sync check
15
+
16
+ on:
17
+ push:
18
+ branches: [main]
19
+ tags: ['v*']
20
+ pull_request:
21
+ branches: [main]
22
+ workflow_dispatch:
23
+
24
+ jobs:
25
+ check:
26
+ runs-on: ubuntu-latest
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - uses: actions/setup-python@v5
31
+ with:
32
+ python-version: '3.13'
33
+
34
+ - name: Run sync check
35
+ id: check
36
+ run: |
37
+ set +e
38
+ out="$(./scripts/check-conda-sync.py 2>&1)"
39
+ rc=$?
40
+ echo "$out"
41
+ {
42
+ echo '## conda-forge sync check'
43
+ echo ''
44
+ echo '```'
45
+ echo "$out"
46
+ echo '```'
47
+ } >> "$GITHUB_STEP_SUMMARY"
48
+ echo "rc=$rc" >> "$GITHUB_OUTPUT"
49
+
50
+ - name: Strict mode on tag push
51
+ if: startsWith(github.ref, 'refs/tags/v') && steps.check.outputs.rc != '0'
52
+ run: |
53
+ echo "::error::pyproject.toml deps drift from conda-forge recipe; release blocked."
54
+ echo "Either prepare the recipe update on the feedstock before tagging,"
55
+ echo "or plan to supersede the autotick-bot PR with a manual update."
56
+ exit 1
@@ -29,7 +29,8 @@ jobs:
29
29
  uses: docker/build-push-action@v6
30
30
  with:
31
31
  context: .
32
+ file: docker/Dockerfile
32
33
  push: true
33
34
  tags: |
34
- ghcr.io/abramsgroup/htpolynet:latest
35
- ghcr.io/abramsgroup/htpolynet:${{ github.sha }}
35
+ ghcr.io/cameronabrams/htpolynet:latest
36
+ ghcr.io/cameronabrams/htpolynet:${{ github.sha }}
@@ -0,0 +1,30 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ unit:
11
+ name: unit (py${{ matrix.python-version }})
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ # floor and current; pyproject requires-python is >=3.10
17
+ python-version: ['3.10', '3.13']
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v5
23
+
24
+ # Tests needing antechamber/tleap/parmchk2/gmx skip themselves when those
25
+ # binaries are absent, so this runner needs no MD toolchain. Everything
26
+ # that does not shell out still runs -- ~250 tests in a few seconds.
27
+ - name: Run unit tests
28
+ run: >
29
+ uv run --python ${{ matrix.python-version }} --extra test
30
+ pytest tests/unit -q
@@ -17,8 +17,6 @@ __pycache__/
17
17
  # C extensions
18
18
  *.so
19
19
 
20
- CLAUDE.md
21
-
22
20
  # Distribution / packaging
23
21
  .Python
24
22
  build/
@@ -105,6 +103,10 @@ ipython_config.py
105
103
  # install all needed dependencies.
106
104
  #Pipfile.lock
107
105
 
106
+ # uv lockfile — regenerated locally; not committed (htpolynet is a
107
+ # library, not a leaf application that needs a pinned dependency tree).
108
+ uv.lock
109
+
108
110
  # PEP 582; used by e.g. github.com/David-OConnor/pyflow
109
111
  __pypackages__/
110
112
 
@@ -0,0 +1,303 @@
1
+ # Changelog
2
+
3
+ All notable changes to htpolynet will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.2.0] - 2026-08-23
11
+
12
+ ### Changed
13
+
14
+ - Container docs' HPC section now leads with `htpolynet gen-slurm-script`
15
+ instead of a hand-written batch script -- the subcommand is already
16
+ Apptainer-aware (`--sif`), but was documented only in `usage.rst`,
17
+ so container users had no reason to find it. The old example
18
+ defaulted to `--gres=gpu:1` and `--nv`, which is actively wrong for
19
+ this image (see the GPU entry under Fixed); replaced with a warning
20
+ explaining why CPU partitions are the right target, plus guidance on
21
+ sizing cores against system size and keeping the submit directory off
22
+ NFS.
23
+ - `rdkit` promoted from the `[smiles]` optional extra to a core
24
+ runtime dependency. Every depot example uses atom-mapped SMILES
25
+ (`[CH:1]`, `[NH2:2]`, etc.), so RDKit is required for any normal
26
+ user workflow; the obabel-only fallback that the extra was
27
+ guarding remains supported but isn't exercised by anything we
28
+ ship. `pip install htpolynet` (or `uv pip install -e .` from the
29
+ repo) now installs RDKit automatically; `'htpolynet[smiles]'` is
30
+ no longer needed (and is gone from `install.rst`).
31
+ - Example 5 (`5-htpb-ipdi.yaml`) retuned for shorter wall-clock.
32
+ The saving comes from a smaller system: the monomer pool drops
33
+ from 125/50/50 to 50/20/20 (IPD/DHT/THT), keeping IPD at
34
+ (2·DHT + 3·THT)/2 so every crosslinker still has both NCO groups
35
+ spoken for at full conversion. Precure anneal segments go 500 →
36
+ 200 ps and postcure postequilibration 1000 → 200 ps.
37
+ Densification was re-balanced for the smaller box in the other
38
+ direction — `initial_density` 50 → 10 kg/m³ to give the long HTPB
39
+ chains room to relax without overlap, and NPT `repeat` 20 → 50 so
40
+ the looser start still reaches target density — so densification
41
+ itself does more work, on a much smaller system. The build still
42
+ converges.
43
+
44
+ ### Added
45
+
46
+ - **CI now runs the unit suite** (`.github/workflows/test.yml`), on pushes
47
+ to `main` and on every pull request, across Python 3.10 and 3.13. Nothing
48
+ ran the tests automatically before, which is how a broken import sat in
49
+ `test_resources.py` aborting collection indefinitely.
50
+ - Tests that shell out to `gmx` / `antechamber` / `tleap` / `parmchk2` now
51
+ skip when those binaries are absent instead of failing, so a runner with
52
+ no MD toolchain still reports the ~250 tests that do not need one (in
53
+ under 4 seconds).
54
+ - Test coverage for `external/slurm.py` (0% -> 98%),
55
+ `external/smiles_input.py` (0% -> 84%), `utils/inputcheck.py`
56
+ (0% -> 70%), and `analysis/plot.py` (6.7% -> 34%), none of which had
57
+ any. Overall coverage 34.4% -> 38.8%. The plot smoke tests were
58
+ checked against the pre-fix module under matplotlib 3.11 and do fail
59
+ there, so they would have caught the `cm.get_cmap` removal.
60
+ - Docker image now carries an `org.opencontainers.image.source` label,
61
+ linking the published GHCR package back to the repository. Without
62
+ it the package is orphaned: it doesn't appear on the repo page and
63
+ doesn't inherit repository-based access permissions.
64
+ - `test` optional-dependency extra (`uv run --extra test pytest tests/unit`),
65
+ with `dev` kept as an alias so both spellings work.
66
+ - `scripts/run_all_examples.sh`: fail-fast preflight that checks
67
+ every required native tool (`htpolynet`, `antechamber`,
68
+ `parmchk2`, `tleap`, `gmx`, `obabel`, `dot`) is on `PATH` before
69
+ starting any build. Better than hitting the first missing
70
+ binary hours into a partial run. Header docstring also gains a
71
+ Prerequisites block pointing at `install.rst` for setup.
72
+ - Docker image now built on `condaforge/miniforge3:latest` (was
73
+ `continuumio/miniconda3:latest`). Miniforge is community-
74
+ maintained, conda-forge only, no Anaconda Inc. terms-of-service
75
+ exposure. Package installs switched from `conda` to `mamba` for
76
+ faster solves. Verified end-to-end: built container's
77
+ `antechamber`, `gmx 2025.4-conda_forge`, `obabel`, `parmed`,
78
+ `rdkit`, and `htpolynet 2.1.0` all callable; `htpolynet
79
+ fetch-example 6 && htpolynet input-check` round-trips.
80
+ - `install.rst` rewritten around the uv + Miniforge workflow: per-
81
+ repo `uv venv` + `uv pip install -e .` for the Python side,
82
+ separate `mamba create -n gromacs` / `mamba create -n ambertools`
83
+ envs for the native MD binaries (both env bins appended to PATH
84
+ in `.bashrc`). Documents `uv tool install --editable .` as the
85
+ way to get a global `htpolynet` command callable from any shell.
86
+ Legacy conda-only one-stop install demoted to a subsection.
87
+ - `htpolynet.utils.profiling` (moved from `htpolynet.profiling`).
88
+ Small utility module — fits utils/ scope; keeps the package root
89
+ focused on actual subpackages. Three internal call sites
90
+ updated.
91
+
92
+ ### Fixed
93
+
94
+ - **API reference documented a module that no longer exists.**
95
+ `docs/source/htpolynetpackage.rst` autodoc'd `htpolynet.driver`,
96
+ removed in the 2.0 refactor, so the package's top-level API section
97
+ rendered empty; it now documents `htpolynet.cli`. The same page was
98
+ missing nine modules that do exist -- most notably the entire
99
+ `repair` subpackage (`repair.cyanate_cap`, `repair.topology_surgery`,
100
+ i.e. the postcure-repair machinery), plus `external.slurm`,
101
+ `external.smiles_input`, `geometry.lattice`, `utils.profiling`, and
102
+ `utils.vmd_viz`. A duplicated `htpolynet.core` heading was merged.
103
+ - `release-history.rst` appeared in no toctree, so the pre-2.0 release
104
+ history (1.0.7.2 back to 0.0.1, which `CHANGELOG.md` does not cover)
105
+ was unreachable from the docs. Linked from `index.rst`; its 2.0.0
106
+ date corrected from 2026-04-15 to 2026-05-07 to match the tag.
107
+ - Two docstrings (`BondTemplate.matches`,
108
+ `utils.profiling.classify_command`) opened bullet lists with no
109
+ preceding blank line, which docutils rejects; both rendered as
110
+ errors. `conf.py` also pointed `html_static_path` at a
111
+ `docs/source/_static` that did not exist. The docs now build with
112
+ zero warnings.
113
+ - **The unit suite could not run at all.** `tests/unit/test_resources.py`
114
+ imported `RuntimeLibrary` from `htpolynet.utils.projectfilesystem` and
115
+ `Software` from `htpolynet.external.software`; neither symbol nor that
116
+ module path survived the 2.0 refactor. Because the imports were at
117
+ module scope, collection aborted for the *entire* `tests/unit` tree, so
118
+ `pytest tests/unit` had been failing outright rather than reporting
119
+ results. Rewritten against the current `SystemLibrary` API (15 tests).
120
+ - Two `test_chain.py` tests asserted exceptions (`'This is a bug - no
121
+ i-chain!'` / `'no j-chain!'`) that no longer exist anywhere in the
122
+ source: `cure/chain.py` deliberately replaced them with graceful chain
123
+ extension, since bonding to a chain-less atom is legitimate for
124
+ non-vinyl chemistry such as HTPB assembly. Rewritten to assert the
125
+ current semantics, plus a new test for the `create_if_missing=False`
126
+ branch. These had been invisible behind the collection failure above.
127
+ - `test_write_top` wrote its scratch file into the repository. The
128
+ autouse `change_test_dir` fixture chdirs each test into a directory
129
+ inside the source tree, and cleanup only ran on the success path, so
130
+ any failure or interrupt left `tests/unit/test_topology/write_test.top`
131
+ behind. Now uses `tempfile.TemporaryDirectory`.
132
+ - **Every plot call crashed on matplotlib 3.11.** `analysis/plot.py`
133
+ called `matplotlib.cm.get_cmap`, deprecated in 3.7 and removed in
134
+ 3.11, at five sites. Since `pyproject.toml` floors matplotlib at
135
+ `>=3.5` with no ceiling, any reasonably fresh install -- including
136
+ the container image, which tracks latest conda-forge -- died with
137
+ `AttributeError: module 'matplotlib.cm' has no attribute
138
+ 'get_cmap'` at the first density trace, i.e. *after* densification
139
+ had already burned its compute. Replaced with a `_get_cmap()`
140
+ helper that prefers the `matplotlib.colormaps` registry and falls
141
+ back to the legacy call only below 3.5. Caught by running example 6
142
+ on Picotte through the container.
143
+ - GPU usability is now judged on whether the gmx build can actually
144
+ drive the detected devices, not merely on whether its GPU support is
145
+ non-`disabled`. conda-forge (and hence our container) ships an
146
+ OpenCL Gromacs build; `gpu_ids` is populated from nvidia-smi and so
147
+ only ever lists NVIDIA devices, which Gromacs no longer drives via
148
+ OpenCL. The previous check passed that combination through, so a
149
+ `gpu_id` from the config reached an `mdrun` that could not honor it.
150
+ New `software.gpu_unusable_reasons()` centralizes the predicate and
151
+ is used by `_mdrun_cmd`, `_enforce_gpu_consistency`, the startup
152
+ banner, and the `grompp_and_mdrun` backstop, which previously
153
+ duplicated a weaker hardware-only version of the test.
154
+ - Container image was missing the `graphviz` system package, so the
155
+ `dot` binary `htpolynet.analysis.plot.draw_reaction_dag` shells out
156
+ to was absent. `pyproject.toml` declares the `graphviz` Python
157
+ binding but the Dockerfile only apt-installed `openbabel` and
158
+ `gosu`. Failure was silent-ish -- `cure/reaction.py` catches the
159
+ exception and logs `reaction_network.png render failed` -- so
160
+ container builds simply came out with no reaction-network figure.
161
+ Found while porting example 6 to Picotte via Apptainer.
162
+ - `htpolynet plots diag` parser templates: the module-path token
163
+ the matcher keyed on was `HTPolyNet.runtime.my_logger` /
164
+ `HTPolyNet.curecontroller.do_iter` from the pre-2.0 namespace.
165
+ After the module reorganization into `htpolynet.core.runtime` /
166
+ `htpolynet.cure.curecontroller`, both lines silently stopped
167
+ matching and the diag parser produced an empty dataframe →
168
+ `IndexError` at first row access. Templates refreshed to the
169
+ current module paths, and the module-name token dropped from
170
+ `pat_idx` so future renames don't break it again.
171
+ - Reaction-network plot (`plots/reaction_network.png`) replaced
172
+ with a bipartite DAG rendered via graphviz `dot` (was a
173
+ spring-layout networkx render that produced tangled, label-
174
+ overlapping diagrams; example 5 was a 30+ node hairball). Each
175
+ molecule is a rounded box; each reaction is a diamond with edges
176
+ from its reactants and an outgoing edge to its product; nodes are
177
+ colored by role (constituent / intermediate / final) and reaction
178
+ stage (param / build / cure / cap / repair). Procession-
179
+ expanded reactions (e.g. example 5's `polymerization` with
180
+ `procession.count: 15`, which `parse_reaction_list` explodes
181
+ into 16 sequential reactions + 15 `A18_I*` intermediates) are
182
+ collapsed back into one node labeled `(×N)` so the diagram
183
+ matches what the user wrote. New runtime dep: `graphviz` (the
184
+ Python wrapper; also needs the system `dot` binary, a separate
185
+ install).
186
+
187
+ ## [2.1.0] - 2026-06-01
188
+
189
+ ### Added
190
+
191
+ - New `htpolynet.repair` package implementing a postcure topology-repair stage that sits between cure and postcure. Drivers can do bond-breaking, atom deletion, atom transfer between residues, and re-templating — operations the monotonic cure/cap reaction machinery cannot perform. `repair/__init__.py` dispatches each `postcure_repair` config entry by its `type:` field; `repair/topology_surgery.py` provides the generic edit primitives (`delete_bonds` with cascading angle/dihedral/14-pair cleanup, `set_atom_attributes`, `reassign_residue`, `add_bonds_with_template` wrapping `make_bonds` + `map_from_templates` + an int-dtype rescue for atom-index columns that pandas float-promotes via NaN-tainted concat); `repair/cyanate_cap.py` carries the first concrete driver. A new `reaction_stage.repair` enum value lets repair-stage reactions ride the existing symmetry-expansion and parameterization paths so the cure-template lookup at surgery time uses a properly parameterized linked-product Molecule. The runtime gains `cfg.postcure_repair`, `Dirs.systems_repair`, and a `do_repair()` hook wired into `do_workflow` between cure and postcure, including a steepest-descent + short NVT relaxation pass to absorb LJ clashes from relocated cap atoms.
192
+ - New `triazine_to_cyanate_cap` repair type: the BADCy-specific driver in `repair/cyanate_cap.py`. At finite cure conversion, the topological A2+B3 BADCy model in example 6 leaves artifacts that don't exist in a real undercured thermoset — free BPA-OH groups and bare triazine C-H sites instead of -O-C#N end-groups. Atom-conservation (the count of unreacted bridge-OH atoms equals the count of dangling crosslinker C atoms across the whole system, exactly) lets the driver dismantle every incomplete triazine (`k < full_bond_count` bonded BPAs) into three independent -C#N fragments via a within-ring C-N matching; the `k` fragments already bonded to a BPA become BPA-O-C#N caps in place, and the remaining `3 - k` are transferred to the nearest unreacted BPA-OH within `cap_search_radius` (greedy matching with radius expansion + global-nearest fallback). After the surgery the heavy-atom neighbors of each deleted sacrificial H absorb its lost charge via `adjust_charges`, keeping the system net-neutral for Ewald. Topology-level outcome on the small test: 19 incomplete TAZ → 57 CYN residues + 1 surviving TAZ + exact heavy-atom conservation, with the C-N bond resolving to GAFF c1-n1 (0.115 nm sp triple) and the BPA-O-C bond to os-c1 (0.132 nm aryl-cyanate ether).
193
+ - Example 6 (`6-cyanate-ester.yaml`) rebuilt around the topological A2+B3 + postcure-repair architecture. The BPA-O-C#N cyanate-ester core is now represented topologically: BPA (90 → 360 at 4x scale, two reactive phenolic O atoms) reacts with bare 1,3,5-triazine TAZ (60 → 240, three reactive ring C-H atoms; ring N atoms additionally atom-mapped to N1/N2/N3 so the repair driver can refer to them by name) in a simple cure-stage aryl-ether substitution — no in-cure ring closure, no `bondcycle_collective` bypass needed because the triazine ring is pre-formed in the TAZ monomer rather than constructed via 3-way cyclotrimerization during cure. A new auxiliary CYN building block (`[CH:1]#[N:2]`, hydrogen cyanide; not inserted into the box, exists only as a parameterization template) plus a `repair`-stage `cap_with_cyanate` reaction supplies the auto-generated `BPA~O1-C1~CYN` linked-product template the repair driver splices into the system for every cap. A `postcure_repair: [{type: triazine_to_cyanate_cap, ...}]` block at the end of the YAML drives the conversion. The header comment block explains the topological model, its tradeoff vs. the previous cyclotrimerization model (no cure-kinetics realism, faithful final-network structure), and how the repair stage restores BADCy residual chemistry.
194
+ - New `htpolynet/profiling.py` module: a `RunProfile` with a stage-stack context manager (`profiling.stage('name')`) and a subprocess-attribution path. Every external command routed through `external/command.run` (and the two raw `subprocess.run` sites in `external/smiles_input`) is timed and classified — `gmx-mdrun`, `gmx-grompp`, `antechamber`, `parmchk2`, `tleap`, `obabel`, `rdkit`, etc. `do_workflow` wraps each stage (`setup`, `initialization`, `densification`, `precure`, `cure` with one nested frame per `iter-K`, `capping`, `postcure`, `final`) so subprocess time is attributed to whichever stage was active when the call happened. At end-of-run a formatted table is written to the log (one line per `logger.info` call, no `my_logger` asterisk padding) and a machine-readable `proj-N/profile.json` is dumped beside `final.top`.
195
+ - New `CURE.controls.min_bonds_per_iteration` knob (default `10`). The bond-search loop now grows the radius until at least this many bonds have been found, falling through to whatever count exists at `max_search_radius`. The effective floor is clamped against `bond_target` (remaining bonds needed to reach `desired_conversion`) and `bond_limit` (the `max_conversion_per_iteration` cap), so demanding e.g. `min_bonds_per_iteration: 50` near end-of-cure never stalls the build. The post-loop "if `nbonds > 0` proceed, else `search_failed`" branch is preserved — accepting fewer bonds than the floor (when max radius is reached) still triggers relax + equilibrate as before. Empirically on the DGEBA/PACM example, `min_bonds_per_iteration=10` cuts the cure iteration count from 41 (with `=1`) to 15; raising further to `=20` saves only one more iteration. The default of 10 was picked off that diminishing-returns curve.
196
+ - The "Radius increased to N nm" log line now also reports the cumulative bond count and the iteration's min-bonds floor as `(X/Y eligible bonds so far)`. Makes it visible at a glance whether the floor or `bond_target` is the active constraint as the search radius grows.
197
+ - `scripts/run_all_examples.sh` — runs every depot example sequentially in its own subdirectory under `./examples-runs/`. Discovers the example ID list by parsing `htpolynet fetch-example --help` (with a `0..4` fallback). Idempotent: skips `fetch-example` if a YAML is already in the per-example directory. Reports per-example exit status and exits non-zero if any example failed. Pass-through after `--` is forwarded to `htpolynet run`.
198
+ - `scripts/run_all_examples.sh --force-reparameterize` — convenience flag that forwards `--force-parameterization --force-checkin` to every `htpolynet run` call. Each example re-runs antechamber/parmchk/tleap on its monomers and overwrites the user cache (`~/.htpolynet/molecules/parameterized/`). Appropriate rigor when consecutive examples share monomers but differ in reaction sets — sidesteps the cache-poisoning interaction between e.g. example 0 (no reactions) and example 1 (cure reactions on STY).
199
+ - All five bundled examples (0–4) are now self-contained YAMLs using the RDKit atom-mapping path on each constituent, so the user names reactive atoms by chemical identity (e.g. `[CH2:1][CH3:2]`) instead of by obabel's output ordering. The legacy `.sh` and `.tgz` siblings have been removed; `htpolynet fetch-example N` now delivers a single `.yaml` for any N. Example 4 (DFDA/FDE) additionally gets a `reactive_atoms` entry for `O1`/`O2` that was missing in its prior shell script (the cap reaction references them). `htpolynet fetch-example 1` delivers the YAML directly; usage collapses to `htpolynet run 1-polystyrene.yaml`. The legacy `1-polystyrene.sh` and `1-polystyrene.tgz` have been removed. `fetch-example` now prefers `.yaml` > `.sh` > `.tgz`.
200
+ - Final-stage save now emits `final.viz.psf` (real bond topology, written via parmed from `final.top` + `final.gro`) and `final.viz.tcl` (drops any bond longer than 3 Å from the display) alongside the existing `final.gro` / `final.top` / `final.tpx` / `final.grx`. Load with `vmd final.viz.psf final.gro -e final.viz.tcl` to view a crosslinked network without the "long bonds across PBC" artifact. The TCL uses `topo getbondlist both` / `topo setbondlist both $list` — the valid topotools 1.x flag values are `type`, `order`, `both`, `none`; the earlier `all` returned an empty list silently and reported "PSF appears to carry no bonds". The TCL also prints the first bond's measured length so the user can verify VMD loaded coordinates in Å.
201
+ - New CLI subcommand `htpolynet make-viz` regenerates `final.viz.psf` + `final.viz.tcl` from any `final.top` + `final.gro` pair without re-running the full workflow. Defaults assume the current directory has `final.top` and `final.gro` (i.e. you've `cd`'d into `systems/final-results/`); override with `-top` / `-gro` / `-prefix`.
202
+ - VMD viz now ships a sidecar `<prefix>.viz.macros.tcl` of constituent-keyed `atomselect` macros, sourced automatically from `<prefix>.viz.tcl`. Two layers: `<NAME>` selects every atom of every instance of constituent `<NAME>` (e.g. `GMA` picks all 75 bis-GMAs in example 2; `DHT` picks all 50 linear HTPB chains in example 5), and `<NAME>_<NNN>` picks one specific instance by global molecule index. The macros are built from `final.grx`'s `molecule` / `molecule_name` columns and compress contiguous atom ranges into VMD `index A to B` tokens (so e.g. example 5's 11 KB macros file covers 225 instances). Lets a user highlight chemical entities like bis-GMA or HTPB whose internal residue scheme reflects building blocks (`BPA`+2×`HIE`, `OB`+`TB`×n+`TBO`×2) rather than the assembled molecule. The residue-level view is untouched — `resname TBO` etc. still work — the new macros are additive. `htpolynet make-viz` gains a `-grx` flag (auto-detected from the `-gro` stem) so the macros are also generated when invoked standalone.
203
+ - Two follow-ons to the `find_template` bystander relaxation, both needed so the small-fragment cure idiom works end-to-end:
204
+ - `Molecule.idx_mappers` previously asserted that the template and instance had the same bystander count on each side, and built atom-pair mappings by flat-concatenating the per-side bystander lists into one zip. With subset-bystander matching the lists can legitimately differ in length, and the flat concatenation misaligns side-A and side-B bystanders across the zip. Pair each region (bonded residues, side-A bystanders, side-B bystanders, oneaways) in its own zip so a length mismatch in one region doesn't shift the alignment of others, and drop the exact-count assertion.
205
+ - `map_from_templates` copies the template's angle / dihedral / pair tables into the system after mapping template atom indices through `temp2inst`. For cyanate-ester cure, the template's CY has more atoms than the post-build system's CY (the cure-reactive C consumes one H during build, so a system CY has one fewer H on that side than the fresh-from-SMILES cure-template CY does); the template's H atom that doesn't exist in the system maps to NaN. Filter rows whose mapped atom indices contain any NaN before concatenating into the system topology — those rows are force-field parameters for atoms that don't exist in the cured system. No effect on chemistries where all template atoms have system counterparts (examples 1-5).
206
+ - `find_template` now uses subset semantics on bystanders. A parameterization-stage template `T` matches a system-instance bond `B` if every (bystander_resname, bystander_atomname) pair declared by `T` also appears in `B`; `B` is allowed to carry additional bystanders that `T` doesn't mention. Oneaway context, atom names, residue names, and the `intraresidue` flag still require exact equality. When multiple templates match, the one with the **most** bystanders declared wins, so chain-extension templates produced by `bondchain_expand_reactions` (which carry specific bystanders) still beat the bare dimer template when their additional context is exactly the in-chain instance's. This unblocks the "small-fragment cure reactant" idiom in cases like cyanate-ester cure, where `CY.C1` is intramolecularly bonded to `BPA.O1` in every BCY-embedded instance — the bare CY+CY dimer template carries no BPA bystander, but the BPA bystander is structural context, not bond chemistry, and the subset rule lets the small template match anyway. Verified: example 1's iter-2 chain-context bond still picks the trimer chain-extension template over the bare dimer template via strict-oneaway discrimination; example 6's iter-1 CY-CY-in-BCY bond now matches the CY+CY cure template via subset-bystander relaxation.
207
+ - Fixed: tleap-input ordering in `external/ambertools.py` ran `check mymol` *before* `loadamberparams <frcmod>`, so any GAFF-coverage gap that parmchk2 had already patched (e.g. `h5-ce-n2` on cyanate-ester C=N–C=N dimer templates) still showed up in tleap's output as an early `Error!`. The run-wrapper's override needle then fired and aborted the parameterization, even though tleap actually completed and the `.top`/`.crd` files were valid. Reordered to load the frcmod *before* the check so the patched parameters are in scope when the molecule is validated. Unblocks new depot example 6 (cyanate-ester thermoset) whose C=N–C=N open-chain cure dimer falls in a GAFF coverage gap that parmchk2 patches by analogy. Other examples are unaffected — for chemistry where parmchk2 emits no patches, the reorder is a no-op.
208
+ - Fixed: cached monomer `.grx` files in `~/.htpolynet/molecules/parameterized/` carry *reactivity-related* attributes (`z`, `sea_idx`, `bondchain`, `bondchain_idx`) that are YAML-dependent — they reflect the reactions defined for the *run that wrote the cache*, not anything intrinsic to the monomer. Running example 0 (liquid styrene, no reactions) wrote `STY.grx` with all-zero z; running example 1 (polystyrene) afterward then loaded that cache and produced 0 candidate atoms in the cure bond search, silently stalling at "Radius increased to N nm (0/10 eligible bonds so far)" all the way out to the max radius. Fix: in the cache-hit branch of `_generate_molecule`, for monomers (no generator), re-run `initialize_monomer_grx_attributes()` against the current run's `zrecs` so z/sea_idx/bondchain are derived from this YAML rather than inherited from a stale cache. The cache itself can still be written with run-specific z values; only the load-time interpretation is hardened.
209
+ - Fixed: corollary of the monomer-cache-poisoning fix. When STY was first poisoned with z=0 by example 0, the subsequent example-1 run generated and cached the cure-stage dimer (`STY~C1-C2~STY.grx`) and the cap (`STYCC.grx`) with *empty* `bondchain` data — the dimer's `chain_manager.injest_bond` no-ops when neither atom is in a chain, which is exactly what happens when the upstream monomer's chain_manager was empty at the time. On the next example-1 run, the cached dimer loaded with 0 chains, `bondchain_expand_reactions` found no 4-atom chains to extend, and zero chain-context templates were generated — so CURE iteration 1 worked (only the dimer template was needed) but iteration 2 raised "you have a bond for which I cannot find a template" because the C1-C2 bond now had a `oneaway` STY chain partner that no available template captured. Fix: after loading a build product from cache, compare the total chain-atom count carried by the cached `chain_manager` against the sum across the product's reactants' `chain_manager`s; if the cache carries fewer atoms (either zero chains, or a partial chain — e.g. example 2's hetero-dimer `STY~C1-C2~HIE` came out length-3 instead of length-4), treat as stale, reset the molecule's `TopoCoord`/`chain_manager`/`bond_templates`/`reaction_bonds`/`sequence` to a blank state, re-parameterize via the normal `generate()` path, and overwrite the cache. The state reset is needed because the cache-load steps populate `TopoCoord` (which `generate()` will then re-merge reactants into) and the half-loaded state ends up float-promoting the `globalIdx` column on the merged dataframe, crashing the prebonding-mol2 writer. Verified on examples 1 and 2: regenerates the affected dimers, after which `bondchain_expand_reactions` produces the expected chain-extension templates (3 for example 1, 32 for example 2 — up from 12 before).
210
+ - New depot example `6-cyanate-ester.yaml`: bisphenol-A dicyanate ester (BADCy) thermoset. The BCY constituent is assembled at param-stage from a BPA bisphenol-A core plus two single-carbon `CY` cyanate end-groups (formaldimine, `[CH2:1]=[NH:2]` — drawn in the sp2 imino-formate active form so the cure-stage triazine-forming C-N bonds have one sacrificial H pre-allocated on each side). Mirrors example 2's `GMA = BPA + 2 HIE` build pattern. The cure stage forms C-N bonds between cyanate end-groups on different BCYs via a single `cyclize` reaction; three such bonds among three monomers close into the 1,3,5-triazine ring (the characteristic crosslink of a cured cyanate ester). The `bondcycle_collective` ring-suppression check is C-C-specific via the `ChainManager`, so the heteroatom triazine ring is allowed to close unhindered. Available as `htpolynet fetch-example 6`. Note: pair with `--force-parameterization --force-checkin` when extending the YAML to cover atoms not previously named in any reaction (e.g. CY's N1) — cached build products inherit `zrecs`-derived `z` values from the prior YAML's reactions and won't pick up newly-added reactivity otherwise.
211
+ - `write_top` now casts known-int columns (atom indices, function codes, dihedral periodicities, `nrexcl`, etc.) to pandas' nullable `Int64` before serialization, so they emit as e.g. `2` rather than `2.0`. The float form had been silently accepted by `gmx grompp` but rejected by `parmed`'s gromacs top reader, which broke the new `.viz.psf` generation.
212
+ - `gmx --version` output is now parsed for `GPU support:` (CUDA, OpenCL, SYCL, disabled) and shown alongside the version line in the startup banner.
213
+ - Consistency check: if the YAML config sets `mdrun_options.gpu_id` but the installed gmx was built without GPU support, or no GPU devices are visible on the host, the option is dropped and a warning is logged. This prevents the runtime crash that `gmx mdrun -gpu_id 0` produces when zero devices are detected.
214
+ - Cache hits during parameterization are now logged at INFO ("Using cached parameterization for `<name>`") instead of DEBUG, plus a post-loop summary line tallying reused vs freshly-parameterized molecules and a reminder of the `--force-parameterization --force-checkin` flags to invalidate stale entries. Pairs with the new "Parameterization caching" section in the user-guide.
215
+ - The `-restart` flag now emits a prominent runtime warning that resumption is experimental and known to fail at the first cure-stage topology update; the argparse help string is annotated likewise, and `docs/source/user-guide/usage.rst` carries an expanded warning explaining the root cause (in-memory cure state is not fully reconstructible from `cure_state.yaml` + on-disk topology files). Pre-cure stages still resume correctly; this section is parked pending a redesign of cure-state persistence.
216
+ - Fixed: `htpolynet run -restart` failed in `CureState.from_yaml` with a `ConstructorError` for the `!!python/object:` tag, because curecontroller's loader was `yaml.FullLoader` (which recent PyYAML tightened to reject Python object tags) while the matching `yaml.dump(self)` writes those tags. Switched to `yaml.Loader` to match what `checkpoint.py` already uses.
217
+ - Fixed: rebuild `self.chain_manager` from the reloaded coordinates on restart. `do_initialization` is correctly skipped by the checkpoint decorator on resume, but it's also where `chain_manager` was being constructed, so subsequent stages (`do_cure`) hit `AttributeError`. `do_workflow` now reconstructs it from the loaded TopoCoord whenever a checkpoint payload is present.
218
+ - Fixed: `htpolynet run -restart` could die with `shutil.SameFileError` when the userlibrary search fell through to `projPath` and the cwd already lived inside it (so the source file IS the destination). `projectfilesystem.py` now uses a `_safe_copyfile` helper that no-ops when src and dst resolve to the same path.
219
+ - Fixed: example 2 HIE constituent's SMILES used `[C:1]` (zero implicit H by SMILES bracket-atom rules) instead of `[CH:1]`, so the α-carbon was emitted at valence 3, antechamber typed it `c2`, and tleap failed with "no angle parameter for o - c2 - os". Documented the bracket-atom H-count gotcha in `docs/source/user-guide/molecular-structure-inputs.rst`.
220
+ - Fixed: the RDKit SMILES path now goes through an SDF (molfile) intermediate to obabel rather than PDB. PDB does not carry bond orders, so obabel had to re-infer them and frequently mis-assigned a carbonyl carbon as the alkene sp2 type (`C.2` from a `C-O` single bond rather than `C.2`+`O.2` double-bond pair), which propagated to GAFF as `c2` instead of `c` and broke tleap with "no angle parameter for o - c2 - os" on monomers with ester groups (e.g. HIE in example 2). SDF preserves bond orders, so obabel emits the right sybyl types and antechamber assigns the correct GAFF types.
221
+ - Fixed: SMILES-generated mol2 files were being written to `projPath/lib/molecules/inputs/<NAME>.mol2` because `Runtime.__init__` runs after `pfs._setup_project_dir` has `chdir`'d into the project directory. `pfs.checkout()` looks in the *user library* (`rootPath/lib/...`), so the files were unfindable and molecule generation fell through to a `BPA.pdb`/`STY.pdb` assertion. `materialize_smiles_inputs` is now invoked with an absolute `inputs_dir` rooted at the user library, and `htpolynet run` pre-creates `lib/molecules/{inputs,parameterized}/` at startup so the library is wired up even when the user's working directory had no `lib/`.
222
+ - Constituents in the YAML config may now carry a `smiles:` key. When present, htpolynet generates `lib/molecules/inputs/<NAME>.mol2` itself before parameterization, eliminating the obabel/sed boilerplate that example shell scripts have historically duplicated. Reactive atom names are set via either `rename_atoms: {<1-based-index>: <name>}` (obabel path, always available) or `reactive_atoms: {<smiles-map-num>: <name>}` (RDKit path, used when the SMILES contains `[*:N]` atom-mapping tokens and RDKit is importable). RDKit is an optional extra: `pip install 'htpolynet[smiles]'`; the container ships it by default.
223
+
224
+ - New `docker-entrypoint.sh` that auto-detects the host owner of the `/work` bind mount and drops privileges via `gosu` before invoking `htpolynet`. Users no longer need to set `--user`, `HOST_UID`/`HOST_GID`, or any other env vars — output files are written with host ownership automatically. The script also writes an `/etc/passwd` entry for the runtime uid so `gosu` resolves `HOME` to `/home/htpolynet` rather than falling back to `/`.
225
+ - Entrypoint dispatches by inspecting the first argument: if it resolves to an executable on `PATH` (`bash`, `python`, `obabel`, ...) it is exec'd directly; otherwise it is treated as an `htpolynet` subcommand. This makes it possible to run `docker compose run --rm htpolynet bash 1-polystyrene.sh --run` (i.e. drive the example shell scripts that themselves call `obabel`/`htpolynet`).
226
+
227
+ ### Changed
228
+
229
+ - Docker-related files moved from the repo root into a new `docker/` subdirectory: `docker/Dockerfile`, `docker/compose.yml`, `docker/docker-entrypoint.sh`. The GH Actions build workflow and the docs `curl -O` URL are updated to match.
230
+ - Dockerfile installs `gosu` and uses the new entrypoint script.
231
+ - `compose.yml` simplified: no `user:` field; no `HOST_UID`/`HOST_GID` substitution. The entrypoint handles uid mapping at runtime.
232
+ - `compose.yml` bind mount uses `${PWD}:/work:Z` so SELinux-enforcing hosts (Fedora, RHEL, openSUSE Tumbleweed, ...) relabel the host directory to `container_file_t`; without this the container is denied writes regardless of POSIX permissions. Harmless on non-SELinux systems.
233
+ - `compose.yml` sets `MPLCONFIGDIR=/tmp/matplotlib` in the environment to silence matplotlib's "not a writable directory" warning.
234
+
235
+ ### Fixed
236
+
237
+ - `_do_pap` previously applied the `_nonempty_directives` guard only to the anneal branch; preequil and postequil ran whenever the section was truthy. That broke for any YAML that defined `precure: preequilibration: ...` without an explicit `precure: postequilibration` — `_apply_runtime_defaults` injects the runtime-default postequilibration block (`ps: 0`, i.e. "no postequilibration"), `TC.equilibrate` returns `None` for `ps: 0`, and the trailing `trace('Density', edr_list, ...)` crashes with `'NoneType' object is not iterable`. Same guard now wraps all three branches, mirroring the existing anneal pattern, with a comment explaining why the postcure-default ps=0 default behaves as it does.
238
+ - Example 6 (postcure anneal) first cycle segment changed from `ps: 20` to `ps: 0`, matching example 3's pattern. The earlier value pushed `annealing_time[0]` to 20 ps while `init_t` was 0, tripping `gmx grompp`'s "First time point for annealing > init_t" fatal error at the postcure stage; the leading ps=0 segment exists purely to anchor the annealing protocol at simulation time 0.
239
+ - `Topology.rep_ex` was shifting the per-copy `resnr` by `c` (the copy index) instead of `c * residues_per_copy`, so when a multi-residue molecule (e.g. the assembled HTPB chains DHT/THT in example 5, ~41 residues each) was replicated `N` times, the resid ranges of successive copies overlapped almost completely. Single-residue monomers like IPD happened to work because `c * 1 == c`, which is why no prior example hit this. The collision surfaced downstream in `Molecule.idx_mappers` (CURE iter-1 topology update): the resid-keyed filter pulled atoms from several distinct instances at once, the atomName merge fanned out, and the same template atom got mapped to multiple instance atoms, tripping the "temp_idx N already claimed" sanity check. Fix: capture `resnr_per_copy = max(resnr)` before the concat and use it as the shift unit. Existing init.gro/init.top files with corrupted resids must be regenerated (delete `proj-*` and re-run `do_initialization`).
240
+ - `TopoCoord.bondcycle_collective` crashed with `AttributeError: 'NoneType' object has no attribute 'added_bonds'` when a cure bond's endpoints weren't part of any vinyl C-C bondchain (e.g. the urethane O-C linkages between TBO oxygen and IPDI formyl carbon in example 5). The chain-manager's `injest_bond` is a no-op when both atoms are outside the chain graph (and `create_if_missing=False`), so the subsequent `chain_of(r.ai)` returns `None`. Such bonds can't form a C-C bondcycle by chemistry — guard the loop and skip them.
241
+ - `Molecule.generate_conformers` now reuses existing conformer `.gro` files instead of regenerating them on every invocation. The check is on file presence in the cwd (`molecules/parameterized/`), so it kicks in equivalently on `-restart` and on re-runs in an existing proj dir. Changing `count` upward still triggers regeneration because the expected files won't all be present. For example 5 (HTPB chains use 6 gromacs-generated conformers per stereoisomer per long-chain monomer), this skips a substantial amount of work on every restart.
242
+ - Dockerfile: pre-create `/home/htpolynet` with mode `0777` so named docker volumes mounted there inherit a world-writable initial state. Without this, a fresh `htpolynet-home` volume came up owned by root and the non-root container user could not create `~/.htpolynet`, `~/.config/matplotlib`, etc.
243
+ - ParmEd `GromacsWarning: The [ pairs ] section contains N exceptions that aren't 1-4 pairs; make sure you know what you're doing!` at end of run. CURE can shorten the topological distance between two atoms previously templated as a 1-4 pair down to 1-3 (a new cure bond shortcuts the original 3-bond path), but nothing was pruning those now-invalid pair entries. New `Topology.prune_stale_14_pairs()` walks the bondlist and drops any `[ pairs ]` entry whose endpoints aren't actually 1-4 in the post-cure graph (uses the existing `bondlist.partners_of`, so it's O(degree³) per pair — fast). Wired into `Runtime.save_data` just before `write_top`; an INFO log line reports the count when any entries get pruned. On the DFA/FDE example 4 build (~23k pairs total) it dropped 40 stale 1-3 pairs.
244
+ - Silent no-op config keys in the depot example YAMLs: `initial_search_radius` (schema is `search_radius`) and `late_threshhold` (schema is `late_threshold`, no extra `h`) were being silently swallowed by `dict.get(key, default)` because the values happened to match defaults. Renamed in all four CURE-bearing examples (1, 2, 3, 4). Behavior unchanged but the docs can now quote the keys honestly.
245
+ - Silent no-op `nconformers:` keys on FDE and DFA in example 4. The runtime reads conformer settings from a `conformers:` sub-block (with `count`, `generator`, `minimize` keys); the flat `nconformers:` line was never read. Dropped.
246
+ - Default `CURE.controls.min_bonds_per_iteration` is now `10` (was effectively `1`, gated by `while nbonds == 0`). This is silent for users with custom YAMLs that don't pin the key; rerun behavior shifts toward fewer, larger CURE iterations.
247
+
248
+ ### Documentation
249
+
250
+ - Container-usage page rewritten around the entrypoint-driven uid mapping; covers SELinux + `:Z` and the role of the `htpolynet-home` named volume.
251
+ - Full rewrite of every short-build tutorial against the current self-contained-YAML workflow. Tutorial directory names now match the depot stem: `2-DGEBA-PACM/` → `3-pacm-dgeba-epoxy-thermoset/`, `3-VE-STY/` → `2-bisgma-styrene-thermoset/`, and a brand-new tutorial 4 (`4-dfda-fde-epoxy-thermoset/`) was written. All cross-references (`ve_*` → `bgs_*`, `dgeba_*` → `pde_*`, new `dfe_*`) renamed accordingly. Each tutorial walks the YAML block-by-block via `literalinclude`, drops the obsolete `run.sh`/`obabel`/`sed` monomer-prep machinery, and points readers at the new `profile.json` and `min_bonds_per_iteration` knob where relevant. Tutorial 0's results page now ships the `final-box.png` VMD render.
252
+ - `scripts/run_all_examples.sh` documented in-script via its header block.
253
+ - Removed the legacy `src/htpolynet/resources/cfg/` directory (12 orphaned config snippets with no Python references; pre-example-depot artifacts). Updated the one `:download:` reference in `usage.rst` that pointed to a file in there.
254
+
255
+ ## [2.0.1] - 2026-05-12
256
+
257
+ ### Changed
258
+
259
+ - `compose.yml`: bind-mount source switched from `.` to `${PWD}` so a single shared `compose.yml` referenced via `docker compose -f` mounts the caller's working directory rather than the file's directory.
260
+ - `compose.yml`: `user:` field now reads `${HOST_UID}` / `${HOST_GID}` instead of `${UID}` / `${GID}` — bash's `UID` is read-only and `GID` is not exported, so the original form silently fell back to `0` (root) and broke writes into the bind mount under rootless Docker.
261
+ - `compose.yml`: container now gets a persistent `HOME` via a named `htpolynet-home` docker volume — without this, `~/.htpolynet` resolved to `/.htpolynet` (root of the container fs) for the non-root user and the user cache could not be created. The named volume also keeps parameterized monomers/oligomers around across `docker compose run --rm` invocations.
262
+
263
+ ### Fixed
264
+
265
+ - Dockerfile header comments: removed duplicated `htpolynet` token in the example `docker run` invocations (the `ENTRYPOINT` already provides it) and added `--user $(id -u):$(id -g)` so output files are not owned by root.
266
+
267
+ ### Documentation
268
+
269
+ - Container-usage page now notes that the image is published only to GHCR (a bare `docker run htpolynet` resolves against Docker Hub and fails) and shows a `docker tag` shortcut for a local alias.
270
+ - Added a `curl -O` one-liner for fetching `compose.yml` directly from the repo.
271
+
272
+ ## [2.0.0] - 2026-05-07
273
+
274
+ ### Changed
275
+
276
+ - Package renamed from `HTPolyNet` to `htpolynet` (fully lowercase) for PEP 8 compliance and PyPI consistency.
277
+ - Runtime now logs the HTPolyNet git commit hash at startup, with a warning when uncommitted changes are present.
278
+
279
+ ### Added
280
+
281
+ - Apptainer/Singularity container support: distributed as a `.sif` image for reproducible execution on HPC clusters.
282
+ - New `gen-slurm-script` subcommand generates a ready-to-submit SLURM batch script from an htpolynet YAML config file.
283
+
284
+ ### Fixed
285
+
286
+ - Chain-expansion bug: bond-chain `ChainManager` was not rebuilt for monomers on the fetch path, causing `bondchain_expand_reactions` to produce no chain-extended oligomers in runs that reused cached parameterizations.
287
+
288
+ ## [1.0.9] - 2025-01-01
289
+
290
+ ### Added
291
+
292
+ - `minimum_bondcycle_length` parameter to allow for cyclic polymerization above a certain threshold length.
293
+
294
+ ### Fixed
295
+
296
+ - Rings not transferred from monomer templates if they are pre-parameterized.
297
+ - Atom indexes in bondchain structure not remapped after atom deletion.
298
+
299
+ ## [1.0.8] - 2024-01-04
300
+
301
+ ### Changed
302
+
303
+ - Uses `chordless_cycles` to find rings; `ringidx` is no longer a unique atom attribute; improved ring-pierce detection.
@@ -0,0 +1,50 @@
1
+ cff-version: 1.2.0
2
+ message: >-
3
+ If you use htpolynet in published work, please cite the SoftwareX article
4
+ under `preferred-citation`, along with the GAFF and Gromacs papers listed
5
+ in the documentation.
6
+ title: htpolynet
7
+ abstract: >-
8
+ Automated molecular-dynamics system builder for amorphous network polymers.
9
+ Generates atomistic models of cross-linked polymer networks, together with
10
+ the Gromacs topology and parameter files needed to simulate them, from only
11
+ the monomer structures, a description of the polymerization chemistry, and a
12
+ handful of system-size and composition options. Atom typing and parameter
13
+ generation use the General Amber Force Field.
14
+ type: software
15
+ authors:
16
+ - family-names: Abrams
17
+ given-names: Cameron F.
18
+ email: cfa22@drexel.edu
19
+ affiliation: Drexel University
20
+ repository-code: https://github.com/cameronabrams/htpolynet
21
+ url: https://htpolynet.readthedocs.io/
22
+ license: MIT
23
+ version: 2.1.0
24
+ date-released: '2026-06-01'
25
+ keywords:
26
+ - molecular dynamics
27
+ - crosslinked polymers
28
+ - thermosets
29
+ - polymer networks
30
+ - Gromacs
31
+ - GAFF
32
+ preferred-citation:
33
+ type: article
34
+ title: >-
35
+ HTPolyNet: A general system generator for all-atom molecular simulations of
36
+ amorphous crosslinked polymers
37
+ authors:
38
+ - family-names: Huang
39
+ given-names: Ming
40
+ - family-names: Abrams
41
+ given-names: Cameron F.
42
+ email: cfa22@drexel.edu
43
+ affiliation: Drexel University
44
+ journal: SoftwareX
45
+ volume: 21
46
+ start: 101303
47
+ year: 2023
48
+ month: 2
49
+ issn: 2352-7110
50
+ doi: 10.1016/j.softx.2022.101303
@@ -0,0 +1,103 @@
1
+ # Working on htpolynet
2
+
3
+ ## Roadmap and changelog
4
+
5
+ `ROADMAP.md` holds upgrades we have identified but not done. `CHANGELOG.md`
6
+ holds what shipped, in Keep-a-Changelog form with a live `[Unreleased]`
7
+ section.
8
+
9
+ Keep both current as a matter of course, without being asked:
10
+
11
+ - When we decide *not* to do something now — a deferred fix, an idea worth
12
+ keeping, a limitation we chose to live with — add it to `ROADMAP.md` with
13
+ enough context to act on it months later. An entry that just says "make
14
+ Gromacs faster" is worthless; say which build, why it is slow, and what
15
+ the tradeoff is.
16
+ - When a roadmap item ships, delete it from `ROADMAP.md` and describe it in
17
+ `CHANGELOG.md` under `[Unreleased]`.
18
+ - Surface relevant roadmap items unprompted when we touch related code.
19
+
20
+ ## Running the tests
21
+
22
+ ```
23
+ uv run --extra test pytest tests/unit -q
24
+ ```
25
+
26
+ `dev` is an alias for the `test` extra; both work.
27
+
28
+ Three test modules shell out to external binaries — `test_parameterize_react`
29
+ needs antechamber/parmchk2/tleap/gmx, and the two `test_gromacs_*` modules
30
+ need gmx. They skip when those are absent rather than failing, which is what
31
+ lets CI run on a plain runner. With the tool chain present the suite takes a
32
+ couple of minutes; without it, about four seconds.
33
+
34
+ ## The test suite runs inside the source tree
35
+
36
+ `tests/conftest.py` has an autouse `change_test_dir` fixture that chdirs each
37
+ test into `tests/unit/<module_name>/` if that directory exists, otherwise
38
+ `tests/unit/`. Both are inside the repo. So a test that writes a file to the
39
+ working directory litters the source tree, and cleanup that runs only on the
40
+ success path leaves the file behind whenever the test fails or is
41
+ interrupted. Write scratch files to `tmp_path` or a
42
+ `tempfile.TemporaryDirectory` instead.
43
+
44
+ ## Docs must build with zero warnings
45
+
46
+ ```
47
+ uv run --with-requirements docs/requirements.txt --with sphinx \
48
+ python -m sphinx -b html docs/source /tmp/docbuild
49
+ ```
50
+
51
+ It currently builds clean; keep it that way. Two things that historically
52
+ broke it:
53
+
54
+ - `docs/source/htpolynetpackage.rst` is a hand-maintained list of
55
+ `automodule` directives, so it drifts silently as modules are added,
56
+ moved, or deleted. It once autodoc'd `htpolynet.driver` for months after
57
+ that module ceased to exist. When you add or move a module, add it here.
58
+ - Adding a module to that page renders its docstrings for the first time,
59
+ which surfaces latent RST errors. The usual one is a bullet list with no
60
+ blank line before it, which docutils rejects.
61
+
62
+ ## Releases
63
+
64
+ Use `scripts/release.sh <version>`. It rotates `[Unreleased]` into a dated
65
+ section, bumps the version in `pyproject.toml`, commits, tags, and pushes.
66
+ Pushing the tag is what triggers publication: `release.yaml` builds and
67
+ publishes to PyPI, creates a GitHub Release from the changelog notes, and
68
+ kicks a Read the Docs build. The conda-forge autotick bot then opens a
69
+ feedstock PR.
70
+
71
+ Do not hand-roll any of that. The script's preflight also checks that
72
+ `pyproject.toml`'s runtime dependencies still match the conda-forge feedstock
73
+ recipe — the autotick bot only bumps version and sha, so a dependency change
74
+ we forget to mirror ships a broken conda package.
75
+
76
+ Because the changelog notes become the public release body, keep
77
+ `[Unreleased]` free of internal bookkeeping ("got bundled into commit
78
+ abc1234") and file entries under the right heading.
79
+
80
+ ## The container
81
+
82
+ The image is `ghcr.io/cameronabrams/htpolynet`, built by `docker.yml` from
83
+ `docker/Dockerfile`. It rebuilds weekly on a schedule and on any tag matching
84
+ `v*` or `d*`. A `d*` tag is the way to rebuild the image without cutting a
85
+ release — useful when only the Dockerfile changed.
86
+
87
+ Its Gromacs comes from conda-forge, which means **OpenCL, not CUDA**, and
88
+ generic `AVX2_256` SIMD. Gromacs no longer drives NVIDIA devices through
89
+ OpenCL, so the image cannot use a GPU: on a cluster, target CPU partitions
90
+ and do not request `--gres=gpu` or pass `--nv`. See `ROADMAP.md`.
91
+
92
+ ## Two invariants worth not breaking
93
+
94
+ - **Colormaps go through `analysis.plot._get_cmap()`**, never
95
+ `matplotlib.cm.get_cmap` directly. The latter was removed in matplotlib
96
+ 3.11, and since `pyproject.toml` floors matplotlib without a ceiling, a
97
+ direct call breaks every plot on a fresh install — after densification has
98
+ already spent its compute.
99
+ - **GPU usability is decided by `external.software.gpu_unusable_reasons()`**,
100
+ which is the single place that reconciles detected hardware against what
101
+ the gmx build can actually drive. Do not add ad-hoc `if gpu_ids:` checks
102
+ elsewhere; a weaker hardware-only duplicate of this test used to live in
103
+ `grompp_and_mdrun` and disagreed with it.