htpolynet 2.11.3__tar.gz → 2.11.4__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 (372) hide show
  1. {htpolynet-2.11.3 → htpolynet-2.11.4}/CHANGELOG.md +167 -0
  2. {htpolynet-2.11.3 → htpolynet-2.11.4}/PKG-INFO +1 -1
  3. {htpolynet-2.11.3 → htpolynet-2.11.4}/ROADMAP.md +167 -0
  4. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/install.rst +34 -3
  5. {htpolynet-2.11.3 → htpolynet-2.11.4}/pyproject.toml +1 -1
  6. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/projectfilesystem.py +31 -0
  7. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/runtime.py +70 -2
  8. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/ringcontroller.py +172 -8
  9. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/triplesearch.py +134 -0
  10. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/schema/base.yaml +105 -7
  11. htpolynet-2.11.4/tests/unit/test_checkout_shadowing.py +50 -0
  12. htpolynet-2.11.4/tests/unit/test_overlong_bond_report.py +82 -0
  13. htpolynet-2.11.4/tests/unit/test_ring_cure_schema.py +105 -0
  14. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_ringcontroller.py +115 -0
  15. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_triplesearch.py +65 -2
  16. {htpolynet-2.11.3 → htpolynet-2.11.4}/.claude/settings.json +0 -0
  17. {htpolynet-2.11.3 → htpolynet-2.11.4}/.claude/skills/htpolynet/SKILL.md +0 -0
  18. {htpolynet-2.11.3 → htpolynet-2.11.4}/.envrc +0 -0
  19. {htpolynet-2.11.3 → htpolynet-2.11.4}/.github/workflows/conda-forge-sync.yml +0 -0
  20. {htpolynet-2.11.3 → htpolynet-2.11.4}/.github/workflows/docker.yml +0 -0
  21. {htpolynet-2.11.3 → htpolynet-2.11.4}/.github/workflows/docs.yml +0 -0
  22. {htpolynet-2.11.3 → htpolynet-2.11.4}/.github/workflows/release.yaml +0 -0
  23. {htpolynet-2.11.3 → htpolynet-2.11.4}/.github/workflows/test.yml +0 -0
  24. {htpolynet-2.11.3 → htpolynet-2.11.4}/.gitignore +0 -0
  25. {htpolynet-2.11.3 → htpolynet-2.11.4}/.readthedocs.yaml +0 -0
  26. {htpolynet-2.11.3 → htpolynet-2.11.4}/CITATION.cff +0 -0
  27. {htpolynet-2.11.3 → htpolynet-2.11.4}/CLAUDE.md +0 -0
  28. {htpolynet-2.11.3 → htpolynet-2.11.4}/LICENSE +0 -0
  29. {htpolynet-2.11.3 → htpolynet-2.11.4}/MANIFEST.in +0 -0
  30. {htpolynet-2.11.3 → htpolynet-2.11.4}/README.md +0 -0
  31. {htpolynet-2.11.3 → htpolynet-2.11.4}/docker/Dockerfile +0 -0
  32. {htpolynet-2.11.3 → htpolynet-2.11.4}/docker/compose.yml +0 -0
  33. {htpolynet-2.11.3 → htpolynet-2.11.4}/docker/docker-entrypoint.sh +0 -0
  34. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/Makefile +0 -0
  35. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/README.rst +0 -0
  36. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/make.bat +0 -0
  37. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/requirements.txt +0 -0
  38. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/_static/.gitkeep +0 -0
  39. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/_static/htpolynet-favicon.ico +0 -0
  40. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/_static/htpolynet-landing.jpg +0 -0
  41. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/_static/htpolynet-logo-dark.png +0 -0
  42. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/_static/htpolynet-logo-light.png +0 -0
  43. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/changelog.rst +0 -0
  44. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/conf.py +0 -0
  45. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
  46. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
  47. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
  48. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
  49. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
  50. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
  51. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
  52. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
  53. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
  54. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
  55. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
  56. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
  57. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
  58. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  59. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  60. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  61. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  62. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  63. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
  64. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  65. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  66. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  67. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
  68. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
  69. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
  70. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
  71. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
  72. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
  73. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
  74. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
  75. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
  76. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
  77. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
  78. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  79. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  80. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  81. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
  82. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
  83. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
  84. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
  85. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  86. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  87. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  88. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
  89. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  90. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
  91. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
  92. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
  93. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
  94. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
  95. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
  96. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
  97. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
  98. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
  99. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
  100. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
  101. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
  102. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
  103. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
  104. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
  105. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  106. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  107. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  108. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
  109. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  110. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  111. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  112. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
  113. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
  114. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
  115. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
  116. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
  117. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
  118. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
  119. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
  120. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
  121. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
  122. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
  123. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
  124. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  125. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
  126. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
  127. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
  128. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
  129. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
  130. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
  131. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
  132. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
  133. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
  134. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
  135. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
  136. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  137. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  138. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  139. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
  140. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  141. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  142. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  143. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  144. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
  145. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
  146. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
  147. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
  148. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
  149. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
  150. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
  151. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
  152. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  153. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  154. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  155. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
  156. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  157. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  158. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  159. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  160. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
  161. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
  162. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
  163. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
  164. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
  165. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
  166. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
  167. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
  168. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
  169. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  170. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  171. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  172. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  173. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  174. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  175. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  176. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +0 -0
  177. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
  178. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
  179. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
  180. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/example-tutorials/index.rst +0 -0
  181. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/htpolynetpackage.rst +0 -0
  182. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/index.rst +0 -0
  183. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/references/index.rst +0 -0
  184. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/references/mol2-reference.pdf +0 -0
  185. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/references.bib +0 -0
  186. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/CURE.odg +0 -0
  187. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/bond_filter.odg +0 -0
  188. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/building-a-system.rst +0 -0
  189. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
  190. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  191. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/configs/configs-for-run.rst +0 -0
  192. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/configuration-files.rst +0 -0
  193. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/container-usage.rst +0 -0
  194. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/flow1.odg +0 -0
  195. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/flow1yaml.odg +0 -0
  196. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/hydrogenated.eps +0 -0
  197. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/hydrogenated.fig +0 -0
  198. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/index.rst +0 -0
  199. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
  200. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/periodic-networks.rst +0 -0
  201. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/STY.png +0 -0
  202. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/STYCC.png +0 -0
  203. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  204. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/bond_filter.png +0 -0
  205. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  206. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  207. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  208. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  209. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  210. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/postcure-repair.rst +0 -0
  211. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/program-flow.rst +0 -0
  212. {htpolynet-2.11.3 → htpolynet-2.11.4}/docs/source/user-guide/usage.rst +0 -0
  213. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/check-conda-sync.py +0 -0
  214. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/release.sh +0 -0
  215. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/render-detail.sh +0 -0
  216. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/render-detail.tcl +0 -0
  217. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/render-snapshot.sh +0 -0
  218. {htpolynet-2.11.3 → htpolynet-2.11.4}/scripts/run_all_examples.sh +0 -0
  219. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/__init__.py +0 -0
  220. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/analysis/__init__.py +0 -0
  221. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/analysis/analyze.py +0 -0
  222. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/analysis/plot.py +0 -0
  223. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/analysis/postsim.py +0 -0
  224. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/analysis/utils.py +0 -0
  225. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cli.py +0 -0
  226. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/__init__.py +0 -0
  227. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/bondtemplate.py +0 -0
  228. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/configuration.py +0 -0
  229. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/coordinates.py +0 -0
  230. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/molecule.py +0 -0
  231. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/paramcache.py +0 -0
  232. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/productsplice.py +0 -0
  233. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/topocoord.py +0 -0
  234. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/core/topology.py +0 -0
  235. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/__init__.py +0 -0
  236. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/chain.py +0 -0
  237. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/curecontroller.py +0 -0
  238. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/expandreactions.py +0 -0
  239. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/cure/reaction.py +0 -0
  240. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/__init__.py +0 -0
  241. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/ambertools.py +0 -0
  242. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/command.py +0 -0
  243. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/gromacs.py +0 -0
  244. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/slurm.py +0 -0
  245. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/smiles_input.py +0 -0
  246. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/external/software.py +0 -0
  247. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/__init__.py +0 -0
  248. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/bondlist.py +0 -0
  249. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/lattice.py +0 -0
  250. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/linkcell.py +0 -0
  251. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/matrix4.py +0 -0
  252. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/placement.py +0 -0
  253. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/ring.py +0 -0
  254. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/geometry/templategeom.py +0 -0
  255. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/io/__init__.py +0 -0
  256. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/io/gro.py +0 -0
  257. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/io/mol2.py +0 -0
  258. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/io/pdb.py +0 -0
  259. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/repair/__init__.py +0 -0
  260. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/repair/cyanate_cap.py +0 -0
  261. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/repair/topology_surgery.py +0 -0
  262. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/README.md +0 -0
  263. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/__init__.py +0 -0
  264. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/claude/SKILL.md +0 -0
  265. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
  266. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
  267. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
  268. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
  269. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
  270. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
  271. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
  272. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/README.md +0 -0
  273. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  274. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  275. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  276. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/min.mdp +0 -0
  277. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  278. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  279. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  280. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  281. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  282. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  283. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  284. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  285. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  286. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  287. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  288. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  289. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  290. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
  291. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  292. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  293. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  294. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  295. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  296. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  297. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  298. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  299. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  300. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
  301. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  302. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  303. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  304. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
  305. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
  306. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  307. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  308. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/resources/tcl/render.tcl +0 -0
  309. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/__init__.py +0 -0
  310. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/banner.py +0 -0
  311. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/checkpoint.py +0 -0
  312. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/convergence.py +0 -0
  313. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/dataframetools.py +0 -0
  314. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/inputcheck.py +0 -0
  315. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/logsetup.py +0 -0
  316. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/profiling.py +0 -0
  317. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/stringthings.py +0 -0
  318. {htpolynet-2.11.3 → htpolynet-2.11.4}/src/htpolynet/utils/vmd_viz.py +0 -0
  319. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/__init__.py +0 -0
  320. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/conftest.py +0 -0
  321. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/__init__.py +0 -0
  322. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/config1.gro +0 -0
  323. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/config1.top +0 -0
  324. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/config2.gro +0 -0
  325. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/config2.top +0 -0
  326. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/items31.edr +0 -0
  327. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/items43.edr +0 -0
  328. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/items45.edr +0 -0
  329. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/fixtures/short.mdp +0 -0
  330. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_bondtemplate.py +0 -0
  331. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_cap_placement.py +0 -0
  332. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_chain.py +0 -0
  333. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_completion_bias.py +0 -0
  334. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_conda_sync.py +0 -0
  335. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_configuration.py +0 -0
  336. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_convergence.py +0 -0
  337. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_cure_site_functionality.py +0 -0
  338. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_dataframetools.py +0 -0
  339. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_density_gate.py +0 -0
  340. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_gpu_usability.py +0 -0
  341. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
  342. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
  343. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_inputcheck.py +0 -0
  344. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_linkcell_pierce.py +0 -0
  345. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_mdrun_gpu_options.py +0 -0
  346. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_mol2_bond_fallback.py +0 -0
  347. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_molecule_charge_report.py +0 -0
  348. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_moleculetype_name.py +0 -0
  349. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_multibody_reactions.py +0 -0
  350. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_paramcache.py +0 -0
  351. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_paramcache_ambertools.py +0 -0
  352. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_parameterize_react.py +0 -0
  353. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_placement_and_ringclose.py +0 -0
  354. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_plot_smoke.py +0 -0
  355. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_productsplice.py +0 -0
  356. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_projectfilesystem.py +0 -0
  357. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_relax_instrumentation.py +0 -0
  358. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_repair_charge_neutrality.py +0 -0
  359. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_repair_conversion.py +0 -0
  360. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_resources.py +0 -0
  361. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_ring.py +0 -0
  362. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_ring_pierce_figs.py +0 -0
  363. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_setup_claude.py +0 -0
  364. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_sibling_templates.py +0 -0
  365. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_slurm_script.py +0 -0
  366. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_smiles_input.py +0 -0
  367. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_software_provenance.py +0 -0
  368. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_templategeom.py +0 -0
  369. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_topology/test.top +0 -0
  370. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_topology.py +0 -0
  371. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_transrot_turn_scan.py +0 -0
  372. {htpolynet-2.11.3 → htpolynet-2.11.4}/tests/unit/test_user_frcmod.py +0 -0
@@ -7,6 +7,173 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.11.4] - 2026-09-26
11
+
12
+ ### Added
13
+
14
+ - **A file of your own that replaces a packaged one now says so.** `pfs.checkout`
15
+ searches the user library, then the user cache, then what htpolynet ships, and took
16
+ the first hit silently. Overriding a packaged file is supported and often the point;
17
+ the trap is that a copy taken from an older version keeps that version's settings for
18
+ as long as it stays on the search path, and nothing said which file a run actually
19
+ used.
20
+
21
+ Found the hard way. A study's `npt.mdp`, copied from 2.6.2 and edited in one place,
22
+ stayed on its path across four upgrades. From 2.7.0 the packaged file sets
23
+ `lincs_order = 8`, because at `dt = 0.002` GROMACS' default of 4 is marginal --- it
24
+ was fatal on one chemistry in 7 of 7 builds, with exit codes 1 and 139. The stale
25
+ copy reverted every run to order 4, and the instability that produced was written up
26
+ for weeks as a property of the systems being built.
27
+
28
+ **This bears on the 2.11.3 notes below.** "Eleven of twenty builds died in the
29
+ anneal" is the rate from builds carrying that stale mdp, so it overstates what the
30
+ unrelaxed final batch alone causes. The defect and the remedy are unaffected: the
31
+ bond energies entering the anneal are single-point energies of the structure and owe
32
+ nothing to integration settings, and the paired seed test showed the settle helping
33
+ even at LINCS order 4. Only the headline failure rate is in doubt.
34
+
35
+
36
+ - **A ring cure now refuses a ring that would close around an existing bond.** CURE
37
+ tests every candidate bond for piercing an existing ring; the ring cure has the
38
+ converse problem and tested nothing at all --- `ringcontroller.py` had no reference to
39
+ `bondtest`, `pierces_ring` or `BTRC`. A triazine could therefore form *around* a
40
+ monomer that was already there and thread it permanently.
41
+
42
+ That is what the stretched monomers were. Over ten finished builds, six carried a
43
+ threaded triazine, and the threading bonds are the same bonds found stretched past
44
+ 2 A: 15 stretched, 13 threading, none threading without being stretched. 10 of 11
45
+ were pre-existing monomer backbone bonds. It explains why those bonds sit on monomers
46
+ that took no part in the ring, why a 160 ps anneal left them unchanged to two
47
+ decimals, and why they hold roughly 700 kT without being thermal --- escaping a
48
+ topological trap needs a bond to break, not a barrier to be crossed.
49
+
50
+ The test runs after the closure ladder and before the bonds are formed, which is
51
+ where the question is unambiguous: the loop is down to nearly its final size, so what
52
+ is inside it is what the triazine will enclose. It treats the loop as a triangle fan
53
+ from its centroid rather than as a plane, and images every coordinate against an
54
+ anchor atom, since a centroid of raw wrapped positions gives false positives across a
55
+ periodic boundary.
56
+
57
+ `ring_cure.prefilter_threaded_candidates` applies the same test at candidate time as
58
+ well, to avoid spending a ladder on a ring that is already threaded. It is **off by
59
+ default**, because a candidate loop is three groups a search radius apart: a formed
60
+ triazine's circumscribed radius is about 1.37 A and near enough rigid across 233 of
61
+ them, while the candidate loop encloses roughly nine times that area at a 1.0 nm
62
+ search radius and over twenty at 1.6 nm, which is where late iterations run.
63
+ Threading would carry through the shrink if nothing moved, but the ladder runs six
64
+ stages of NVT at 600 K, so a bond inside the candidate loop need not still be inside
65
+ at closure. Set `ring_cure.reject_threaded_rings: false` to reproduce the old
66
+ behavior entirely.
67
+
68
+ **Measured across three arms, same image, no mdp override.** Filtered builds came out
69
+ clean 6 of 6; unfiltered builds carried a pierced triazine in 2 of 4 --- 4, 2, 0 and 0
70
+ piercings, a mean of 1.5 each. There is no conversion cost: 0.971 to 0.983 in 21 to
71
+ 23 iterations against 0.971 to 0.979 in 20 to 22 without it.
72
+
73
+ The closure-time test declined 2, 10 and 1 candidates across three builds, a mean of
74
+ 4.3 against those 1.5 piercings. Same order of magnitude with overlapping
75
+ distributions, and that is as much as the data supports: at three builds against four
76
+ the smallest two-sided Mann-Whitney p obtainable is 0.057, so the observed 0.47 is no
77
+ more evidence of agreement than of excess. The two are not the same quantity either
78
+ --- a declined candidate is one that *would* have threaded, and the alternative
79
+ `select_disjoint` takes instead may itself thread and be declined in turn, so declines
80
+ bound the piercings prevented rather than counting them.
81
+
82
+ The candidate-time prefilter is a different matter: it discarded 1216 to 4385
83
+ candidates per build to catch what the closure test catches in single digits, and both
84
+ arms finished equally clean --- which is why it stays off by default.
85
+
86
+ ### Fixed
87
+
88
+ - **A ring cure ran at constant volume from first ring to last, so it could not
89
+ densify.** Every ring-cure stage was NVT — the relaxation after each iteration, the
90
+ closure ladder, and the settle — with no constant-pressure step anywhere. Measured
91
+ over 22 iterations of a 233-triazine build, the box stayed at 5.241 nm to four
92
+ decimals and the density at 1155.9 kg/m3 from the first ring to the last, with the
93
+ entire volume change deferred to a single postcure NPT. CURE's density climbs
94
+ through its cure, roughly 1085 to 1170, because its relaxation stages run NPT above
95
+ Tg and are deliberately "the only above-Tg constant-pressure time in a cure".
96
+
97
+ Cure shrinkage cannot be reproduced at fixed volume by construction — Snow measures
98
+ 0.0324 ml/g for BADCy — and a network that forms in a box which cannot respond
99
+ accumulates internal stress with nowhere to put it, which is a plausible route to the
100
+ stretched bonds recorded in `ROADMAP.md`.
101
+
102
+ `ring_cure.relax` now mirrors CURE's `relax.equilibration` exactly --- minimization,
103
+ NVT at 600 K, then NPT at 600 K and 1 bar --- rather than CURE's much longer
104
+ per-iteration equilibration. The whole sequence is above Tg, not just the
105
+ constant-pressure stage: relaxing at 300 K in between two 600 K closure ladders cooled
106
+ the network and would have put a cold, less mobile configuration under the barostat,
107
+ which is a good way to measure no densification and wrongly conclude the stage does
108
+ not work. The closure ladder itself stays constant-volume on purpose: NPT while
109
+ restraints are actively pulling groups together is not a stable combination.
110
+
111
+ - **A ring cure had no cold equilibration, so once it could move, its box only grew.**
112
+ Adding the constant-pressure relax stage above let the box respond, but `relax` ends
113
+ hot. Measured with relax alone over a full build, the box expands thermally for six
114
+ iterations to +27.9% in volume, then comes back down as the network forms: peak to
115
+ minimum is -7.49% in volume and +71.9 kg/m3. The two legs nearly cancel, so the net
116
+ is near zero and the path length is 0.4104 nm --- a frozen box captures none of it.
117
+
118
+ That descending leg is not a measurement of cure shrinkage: 2 ps at 600 K does not
119
+ equilibrate, so it mixes in residual thermal relaxation, and it spans conversion 0.55
120
+ to 0.971. It costs iterations too --- `search_radius` is an absolute length and does
121
+ not scale with the box, so an expanded box encloses fewer groups per sphere, and the
122
+ hot-only arm needed 25 iterations against 22 for the same conversion. A cure is not only shrinkage --- the hot stages enlarge
123
+ the box and a cold stage pulls it back, and on the pairwise route the box travels
124
+ three to nine times further in length than it ends up moving.
125
+
126
+ `ring_cure` now has an `equilibrate` stage identical in shape and in defaults to
127
+ `CURE.equilibrate` --- NPT, 300 K, 1 bar, 50000 steps of 2 fs --- run once per
128
+ iteration after `relax`, through the same code path the pairwise cure uses, so it
129
+ picks up that route's box logging and density series rather than reimplementing them.
130
+ The per-iteration shape of the two cures is now the same.
131
+
132
+ It is also the expensive stage, roughly 99 s against a 280 s iteration. Whether
133
+ 100 ps is the right number for *either* route has never been measured; `ROADMAP.md`
134
+ sketches the study.
135
+
136
+ - **Three `ring_cure` settings could not be set at all**, because they were missing from
137
+ the schema, and ycleptic rejects an unknown key outright rather than ignoring it.
138
+ `ring_cure.relax` and `ring_cure.closure.equilibration` were never exposed, and
139
+ `closure.max_accept` — added in 2.11.1 — was written into `CURE`'s `drag` block by
140
+ mistake, where a config could set it and nothing would read it. All three now sit
141
+ where they belong, and a test asserts that every key the controller honors appears in
142
+ the schema with a matching default.
143
+
144
+ ### Changed
145
+
146
+ - **The installation page now says not to install `htpolynet` from conda-forge.** The
147
+ package published there is several releases behind and cannot currently be updated:
148
+ `htpolynet` depends on `ycleptic`, which is not yet available on conda-forge, so the
149
+ feedstock's automatic version bumps produce a package that cannot import and none has
150
+ been published. What is on conda-forge does install and run, so nothing warns a user
151
+ that they have an old `htpolynet`.
152
+
153
+ The conda-only recipe now installs Python and the MD binaries from conda-forge and
154
+ `htpolynet` itself from PyPI. The warning is scoped to the `htpolynet` package alone
155
+ --- conda-forge remains the recommended source for AmberTools and Gromacs --- and it
156
+ gives the two commands to check the current state rather than asking the reader to
157
+ trust a page that may itself be stale. The container remains the recommendation, and
158
+ the page now says outright that it requires no installation at all.
159
+
160
+ ### Added
161
+
162
+ - **A build now says so when it hands on a bond that is not a bond any more.** At the
163
+ end of a ring cure and again in the final data, any bond longer than 0.2 nm is
164
+ reported, the worst named by atom and residue. Lengths use the minimum-image
165
+ convention, so a bond across a periodic boundary is not counted.
166
+
167
+ This exists because such a bond is otherwise silent: the topology is valid, every
168
+ molecule is neutral, and the run completes. htpolynet-study measured a C-C at 3.20 A
169
+ in two of five *final* structures, unchanged to two decimals by a 160 ps anneal. Ring
170
+ bonds always relaxed; these did not, because they are held by network tension rather
171
+ than by thermal motion — a monomer stretched between parts of the network that a ring
172
+ closure pulled apart, in a ring it was not itself part of.
173
+
174
+ This is detection and not a fix; `ROADMAP.md` has the mechanism and why no remedy has
175
+ been chosen. Anything computed from a structure carrying such a bond inherits it.
176
+
10
177
  ## [2.11.3] - 2026-09-23
11
178
 
12
179
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: htpolynet
3
- Version: 2.11.3
3
+ Version: 2.11.4
4
4
  Summary: Automated MD System Builder for Amorphous Network Polymers
5
5
  Project-URL: Source, https://github.com/cameronabrams/htpolynet
6
6
  Project-URL: Documentation, https://htpolynet.readthedocs.io/
@@ -199,6 +199,173 @@ Coverage as of the last measurement: **38.8%** overall.
199
199
 
200
200
  ## Cure and repair
201
201
 
202
+ - **Nobody has ever checked whether the intra-cure MD stages do anything, and they are
203
+ most of the cost.** Raised by Cameron 2026-09-24: the annealing and relaxation runs
204
+ inside a cure were chosen arbitrarily and have never been justified by a convergence
205
+ study. The budget, per cure iteration, from the shipped defaults:
206
+
207
+ CURE relax.equilibration 6 stages x (min + 1 ps NVT 600 + 2 ps NPT 600) 18 ps
208
+ equilibrate 1 x NPT 300 K, 50000 steps x 2 fs 100 ps
209
+ drag.equilibration disabled by default (trigger_distance 0.0) --
210
+ total ~118 ps
211
+
212
+ ring cure closure.equilibration 8 stages x (min + 1 ps NVT 600) 8 ps
213
+ relax min + 1 ps NVT 600 + 2 ps NPT 600 3 ps
214
+ total ~11 ps
215
+
216
+ **85% of CURE's intra-cure MD is the single 100 ps `equilibrate`**, and nothing
217
+ records what it accomplishes. Note also the order-of-magnitude asymmetry between the
218
+ two routes, which nobody chose deliberately either.
219
+
220
+ **Why it cannot be answered today.** `profiling.stage` wraps whole phases and whole
221
+ iterations, not individual `grompp_and_mdrun` calls, so there is no per-stage wall
222
+ time. And no stage records the quantity it exists to move, so "did it converge" is
223
+ not answerable from any existing output. One exception worth knowing: the ring
224
+ closure ladder already logs its max pair distance per stage at DEBUG
225
+ (`ringcontroller.py`, "ring-close stage"), so that ladder's convergence can be audited
226
+ from a run with debug logging and no new code at all.
227
+
228
+ **A study, in four parts.**
229
+
230
+ *0. Instrument.* Extend profiling to wrap each `grompp_and_mdrun` so `profile.json`
231
+ carries per-stage wall time, and have each stage record the observable it is supposed
232
+ to move: box and density against time for anything NPT (from the `.edr`, so the
233
+ within-stage trajectory is available and not just the endpoint), new-bond length
234
+ against its attenuated `b0` for `relax`, max pair distance for the ring ladder. This
235
+ is the only part that is repo work; it is small, and everything else depends on it.
236
+
237
+ *1. Convergence audit.* One CURE build and one ring-cure build at stock settings.
238
+ One data point already exists and it cuts against the cheap end of the range: 2 ps of
239
+ NPT per iteration does not converge a ring cure's box at all (see the constant-volume
240
+ entry above), so the audit should expect the answer to be tens of ps rather than
241
+ single digits, and should sample within a stage rather than only at its end.
242
+ For each stage ask a single question: at what fraction of its length does the
243
+ observable stop changing? A 100 ps equilibration whose density plateaus at 20 ps is
244
+ five times longer than it needs to be, and that is measurable once, cheaply, rather
245
+ than argued about.
246
+
247
+ *2. Truncation sweep.* For every stage that converges early, halve and quarter it.
248
+
249
+ *3. Null arm.* Remove the stage outright. This is the actual test of Cameron's
250
+ question --- a stage whose removal changes nothing downstream is not earning its
251
+ keep, however well it converges.
252
+
253
+ **Fix the acceptance criteria before running anything**, because every one of these
254
+ arms will produce a build that looks fine. Proposed: final density within a stated
255
+ tolerance of the stock build; conversion-against-iteration curves overlapping; no
256
+ increase in bonds beyond 0.2 nm as counted by `Runtime._report_overlong_bonds`; no
257
+ increase in postcure anneal failures across a fixed set of velocity seeds; and total
258
+ wall time, which is the point. Deciding those numbers afterwards is how a cheaper
259
+ cure gets declared equivalent because it did not obviously break.
260
+
261
+ **Who runs it.** The instrumentation is repo work. The builds are not --- example
262
+ builds belong to htpolynet-sweep, and a cure-physics comparison of this kind is the
263
+ study's kind of work. The ring-cure NPT A/B of 2026-09-24 is the first instance of
264
+ exactly this pattern and its design is worth copying: two arms differing in one stage
265
+ list, same pinned image, both arms written out explicitly so neither inherits a
266
+ default that might move underneath the comparison.
267
+
268
+ - **The ring cure has no cold equilibration stage, so its box cannot breathe the way
269
+ CURE's does.** As of 2.11.4 `ring_cure.relax` ends with NPT at 600 K, which is what
270
+ lets the box respond at all. CURE has that *and* a separate per-iteration
271
+ `equilibrate` --- NPT at 300 K for 50000 steps, 100 ps --- which the ring cure has no
272
+ equivalent of. So the ring cure equilibrates hot and never gets pulled back cold.
273
+
274
+ Cameron's observation is that a cure is not only shrinkage: the 600 K stages enlarge
275
+ the box and the 300 K equilibration pulls it back, so the box cycles every iteration.
276
+ htpolynet-study measured the cycle on three A2+B3 surrogates, at the cold checkpoints
277
+ only --- the 600 K stages log no box at all, so the real amplitude is larger:
278
+
279
+ build iters rises largest rise net path length
280
+ r1 17 6 +0.0120 -0.0430 0.1450
281
+ r2 16 5 +0.0140 -0.0420 0.1360
282
+ r3 16 8 +0.0260 -0.0240 0.2100
283
+
284
+ The box travels three to nine times further than it ends up moving. A ring cure over
285
+ 22 iterations had a path length of exactly 0.0000 nm.
286
+
287
+ **Deliberately deferred, and by whom.** Presented with the choice between mirroring
288
+ CURE's `relax.equilibration` and mirroring its full `equilibrate`, Cameron chose the
289
+ cheaper one. The A/B measuring whether it suffices is what should settle this; 100 ps
290
+ per iteration against a 150-iteration cap is not a cost to take on speculatively.
291
+
292
+ **MEASURED 2026-09-24, and the cheap shape is not enough.** A two-arm A/B, both arms
293
+ on the same pinned image, differing only in the relax stage list:
294
+
295
+ arm box (nm), successive iterations rho (kg/m3) path
296
+ npt r1 5.5566 -> 5.6882 970 -> 904 0.1315
297
+ npt r2 5.5977 -> 5.6553 -> 5.6614 949 -> 917 0.0637
298
+ control 5.2382 / 5.2435, unchanged x3 1157 / 1154 0.0000
299
+ baseline 5.2405 1156.0 0.0000
300
+
301
+ The control arms are frozen to five decimals, which establishes that the constant
302
+ volume was the relax stage list alone and nothing else that changed between 2.11.1
303
+ and 2.11.4.
304
+
305
+ **Read the whole run, not its first quarter.** Over a complete 25-iteration build the
306
+ hot-only box has two regimes, and only the first was visible early:
307
+
308
+ iter 1 6 12 18 21 24 25
309
+ box 5.5977 5.7223 5.6639 5.6701 5.6442 5.5757 5.5939
310
+ rho 948.5 887.9 915.6 912.7 925.3 959.8 950.4
311
+ path 0.4104 nm, net -0.0038 nm
312
+
313
+ Thermal expansion to iteration 6, then the box comes back **down** as the network
314
+ forms: peak to minimum is -7.49% in volume, +71.9 kg/m3, 0.0844 ml/g. The net is
315
+ near zero only because the two legs nearly cancel, which is exactly why path length
316
+ rather than net is the statistic to quote. A frozen box captures none of it.
317
+
318
+ This retires two judgements made on the first four iterations --- mine, that a
319
+ still-expanding box was "differently wrong", and the reading that the climb had no
320
+ bound. Nor is there a conversion ceiling: the hot-only arm finished at 233 rings and
321
+ conversion 0.971, the same endpoint as both controls and the baseline, in 25
322
+ iterations against 22. The 0.09-0.10 conversion deficit at matched iteration is real
323
+ but is a **rate** effect worth about 14% in iterations, not a limit. Its mechanism is
324
+ worth keeping: ``search_radius`` is an absolute length and does not scale with the
325
+ box, so an expanded box encloses fewer groups per sphere and a triple is harder to
326
+ find.
327
+
328
+ **What the descending leg is not** is a measurement of cure shrinkage. 2 ps at 600 K
329
+ does not equilibrate, so that leg mixes in residual thermal relaxation, and it spans
330
+ conversion 0.55 to 0.971. It captures shrinkage; it does not measure it. That, and
331
+ Cameron's instruction to match what the binary cures already do, are what the cold
332
+ equilibration rests on --- not on hot-only being worse, which it is not.
333
+
334
+ What the widening actually tracks is **concentration**, which is worth knowing on its
335
+ own. Both arms widened for the first time at the same iteration, on the same trigger
336
+ of two candidates against a floor of four, from very different states: 315 unreacted
337
+ groups in a 192.6 nm3 box against 237 in a 143.7 nm3 box --- 1.6352 and 1.6489 groups
338
+ per nm3, within 0.9% of each other, while the arms sat 0.09 apart in conversion and
339
+ 33% apart in raw count. A fixed `search_radius` makes `min_rings_per_iteration` an
340
+ implicit concentration criterion. Since 2.11.4 the search logs that concentration,
341
+ because otherwise the widening looks arbitrary in any cure whose box moves.
342
+
343
+ So a *short* cold stage will not equilibrate either, and CURE's 100 ps is the relevant
344
+ scale rather than an arbitrary one.
345
+
346
+ **Do not score that measurement against CURE's density curve.** CURE's 1085 -> 1170
347
+ is read at its *cold* checkpoints. A ring cure whose only NPT is at 600 K will sit at
348
+ a larger box and a lower density than its own constant-volume baseline, and that is
349
+ the stage working rather than failing. The signal is path length greater than zero,
350
+ and then the trend across hot checkpoints. If a cold stage is added later, the open
351
+ question is whether a short one converges at all or whether the barostat needs
352
+ something like CURE's 100 ps --- which is the other thing the A/B will show.
353
+
354
+ - **Properties measured before the threading filter may carry threaded rings.** The
355
+ filter shipped in 2.11.4; every build made before it could contain a triazine closed
356
+ around a monomer, which happened in 2 of 4 unfiltered builds --- 4, 2, 0 and 0
357
+ piercings, a mean of 1.5 each.
358
+ A threaded monomer is a permanent topological defect carrying a bond stretched past
359
+ 2 A, so it is not obvious that Tg, density or modulus from those builds are unbiased,
360
+ and it is not obvious that they are biased either --- nobody has measured it.
361
+
362
+ The comparison is cheap now that both arms exist: build a small set with
363
+ `reject_threaded_rings` true and false and compare the properties, rather than
364
+ re-running any campaign on faith. Whoever owns a property campaign predating 2.11.4
365
+ should decide whether to rebuild; htpolynet-study raised this about their own and it
366
+ is their call, not the repo's.
367
+
368
+
202
369
  - **A ring cure that stalls near its target has no exit but `max_iterations`.**
203
370
  Reported by htpolynet-study 2026-09-23 from a 2.11.1 build: at conversion 0.97
204
371
  with 24 groups left, nine iterations running (32-40) produced 77 declines and no
@@ -29,6 +29,10 @@ Installation and Prerequisites
29
29
  The default image runs Gromacs on CPUs only. To use an NVIDIA GPU, use
30
30
  the ``:cuda`` tag instead.
31
31
 
32
+ Nothing is installed on your system, and the image is always current ---
33
+ which the ``conda-forge`` package is not; see
34
+ :ref:`the note below <conda_forge_not_recommended>`.
35
+
32
36
  See :ref:`container_usage` for the details: persistent caches, GPU setup,
33
37
  and pinning a release.
34
38
 
@@ -153,14 +157,41 @@ On openSUSE / Fedora / RHEL:
153
157
  Conda-only (simpler one-stop install)
154
158
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
155
159
 
160
+ .. _conda_forge_not_recommended:
161
+
162
+ .. admonition:: Do not install ``htpolynet`` itself from conda-forge
163
+ :class: warning
164
+
165
+ The ``htpolynet`` package on ``conda-forge`` is several releases behind
166
+ and is **not currently recommended**. What is published there installs
167
+ and runs, so nothing warns you --- you simply get an old ``htpolynet``.
168
+
169
+ It cannot be updated at the moment. ``htpolynet`` now depends on
170
+ `ycleptic <https://pypi.org/project/ycleptic/>`_, which is not yet
171
+ available on ``conda-forge``; until it is, the feedstock's automatic
172
+ version bumps produce a package that cannot import, so none has been
173
+ published.
174
+
175
+ You do not have to take this page's word for how far behind it is ---
176
+ the page may itself be stale by the time you read it:
177
+
178
+ .. code-block:: console
179
+
180
+ $ conda search -c conda-forge htpolynet | tail -1 # what conda-forge has
181
+ $ pip index versions htpolynet # what is current
182
+
183
+ This applies only to the ``htpolynet`` package. ``conda-forge`` remains
184
+ the recommended source for AmberTools and Gromacs, as described above.
185
+
156
186
  Using Miniforge (preferred) or any other ``conda``-style installer, you
157
- can manage everything — Python, MD binaries, and ``htpolynet`` itself —
158
- in a single environment:
187
+ can manage Python and the MD binaries in a single environment, then add
188
+ ``htpolynet`` itself from PyPI:
159
189
 
160
190
  .. code-block:: console
161
191
 
162
- $ mamba create -n htpolynet -c conda-forge python ambertools gromacs htpolynet
192
+ $ mamba create -n htpolynet -c conda-forge python ambertools gromacs
163
193
  $ mamba activate htpolynet
194
+ $ pip install htpolynet
164
195
 
165
196
  Then install OpenBabel from your distribution's package manager as
166
197
  described above (OpenBabel via ``conda-forge`` works too but the
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "htpolynet"
7
- version = "2.11.3"
7
+ version = "2.11.4"
8
8
  authors = [
9
9
  { name="Cameron F Abrams", email="cfa22@drexel.edu" },
10
10
  ]
@@ -472,9 +472,38 @@ def resolve_user_library(pathname, default='lib'):
472
472
  return default if os.path.isdir(default) else None
473
473
 
474
474
 
475
+ def _note_if_shadowing(filename, source):
476
+ """Says so when a file of your own replaces one htpolynet ships.
477
+
478
+ Overriding a packaged file is supported and often the point. The trap is that a
479
+ copy taken from an older version keeps that version's settings, silently, for as
480
+ long as it stays on the search path -- so a setting the packaged file has since
481
+ gained never reaches the run, and nothing says which file was used.
482
+
483
+ Seen 2026-09-24: an `npt.mdp` copied from 2.6.2 and edited in one place stayed on a
484
+ study's path across four upgrades. From 2.7.0 the packaged file sets
485
+ ``lincs_order = 8``, because at ``dt = 0.002`` GROMACS' default of 4 is marginal and
486
+ was fatal on one chemistry in 7 of 7 builds. The stale copy reverted every run to
487
+ order 4, and the resulting instability was written up for weeks as a property of the
488
+ systems being built.
489
+ """
490
+ try:
491
+ if _SYSTEM_LIBRARY_ and _SYSTEM_LIBRARY_._root.joinpath(filename).exists():
492
+ logger.warning(
493
+ f'{filename} was taken from your {source} and replaces the copy '
494
+ f'htpolynet ships. That is supported -- but if it was copied from an '
495
+ f'older version it still carries that version\'s settings. Compare it '
496
+ f'against the packaged file after any upgrade.')
497
+ except Exception:
498
+ pass
499
+
500
+
475
501
  def checkout(filename, altpath=[]):
476
502
  """Copies a file to cwd; searches user library, then user cache, then system library.
477
503
 
504
+ A file found in the user library or cache shadows the packaged one, and
505
+ :func:`_note_if_shadowing` says so, because a stale copy is otherwise invisible.
506
+
478
507
  Args:
479
508
  filename (str): path relative to library root
480
509
  altpath (list): extra search directories, defaults to []
@@ -484,8 +513,10 @@ def checkout(filename, altpath=[]):
484
513
  """
485
514
  if _PFS_ and _PFS_.userlibrary and _PFS_.userlibrary.checkout(
486
515
  filename, searchpath=[_PFS_.rootPath, _PFS_.projPath], altpath=altpath):
516
+ _note_if_shadowing(filename, 'user library')
487
517
  return True
488
518
  if _USER_CACHE_.checkout(filename):
519
+ _note_if_shadowing(filename, 'user cache')
489
520
  return True
490
521
  return _SYSTEM_LIBRARY_.checkout(filename)
491
522
 
@@ -14,6 +14,7 @@ from copy import deepcopy
14
14
 
15
15
  import networkx as nx
16
16
  import numpy as np
17
+ import pandas as pd
17
18
 
18
19
  from networkx.algorithms import isomorphism
19
20
 
@@ -31,7 +32,7 @@ from ..cure.reaction import (Reaction, ReactionList, parse_reaction_list, extrac
31
32
  is_reactant, is_ring_closing, reaction_stage)
32
33
  from ..core.productsplice import nearer_site_atoms
33
34
  from ..cure.ringcontroller import RingController, RingCureState
34
- from ..cure.triplesearch import reactive_sites, triple_bonds_dataframe
35
+ from ..cure.triplesearch import bonds_by_atom, reactive_sites, triple_bonds_dataframe
35
36
  from ..external import software as software
36
37
  from ..external.gromacs import insert_molecules, mdp_modify, mdp_get
37
38
  from ..external.smiles_input import materialize_smiles_inputs
@@ -694,7 +695,11 @@ class Runtime:
694
695
  adf = TC.Coordinates.A
695
696
  positions = {int(r.globalIdx): np.array([r.posX, r.posY, r.posZ])
696
697
  for r in adf.itertuples()}
697
- sites, chosen = rc.search(adf, positions, TC.Coordinates.box.diagonal(), resname, groups)
698
+ # a ring that closes around an existing bond threads that monomer through
699
+ # it for good; CURE refuses the mirror image of this and the ring cure did not
700
+ bonds_of = bonds_by_atom(TC.Topology.D['bonds'])
701
+ sites, chosen = rc.search(adf, positions, TC.Coordinates.box.diagonal(), resname,
702
+ groups, bonds_of=bonds_of)
698
703
  if not chosen:
699
704
  if rc.widen():
700
705
  break
@@ -704,12 +709,17 @@ class Runtime:
704
709
  work = rc.close_rings(TC, bdf, gromacs_dict=gromacs_dict)
705
710
  # a ring the ladder could not pull shut would be bonded long and stay that way
706
711
  bdf, chosen = rc.accept(bdf, work, chosen)
712
+ # now that the loop is nearly ring-sized, ask what it actually encloses
713
+ bdf, chosen = rc.reject_threaded(TC, bdf, chosen)
707
714
  if not chosen:
708
715
  rc.state.iter += 1
709
716
  continue
710
717
  rc.form_rings(TC, bdf, sites, chosen, template, template_resids,
711
718
  name_translations=name_translations, atom_names=arm)
712
719
  rc.relax(TC, gromacs_dict=gromacs_dict)
720
+ # the cold half of the cycle: relax ends hot and expanded, and without this
721
+ # the box only ever grows
722
+ rc.equilibrate(TC, gromacs_dict=gromacs_dict)
713
723
  rc.record(chosen)
714
724
  TC.write_gro(f'ring-{rc.state.iter}.gro')
715
725
  TC.write_top(f'ring-{rc.state.iter}.top')
@@ -725,6 +735,7 @@ class Runtime:
725
735
  rc.settle(TC, gromacs_dict=gromacs_dict)
726
736
  pfs.go_proj()
727
737
  self._report_molecule_charges('after ring cure')
738
+ self._report_overlong_bonds('after ring cure')
728
739
  my_logger(f'Ring cure ends: {rc.state.rings} ring(s), conversion '
729
740
  f'{rc.state.conversion:.3f}', logger.info)
730
741
  return {c: os.path.basename(x) for c, x in TC.files.items() if c != 'mol2'}
@@ -845,6 +856,7 @@ class Runtime:
845
856
  if dropped:
846
857
  logger.info(f'Pruned {dropped} stale [ pairs ] entries left over from cure-induced path shortening')
847
858
  self._report_molecule_charges(f'in {result_name}')
859
+ self._report_overlong_bonds(f'in {result_name}')
848
860
  TC.write_grx_attributes(f'{result_name}.grx')
849
861
  TC.write_gro(f'{result_name}.gro')
850
862
  TC.write_top(f'{result_name}.top')
@@ -883,6 +895,62 @@ class Runtime:
883
895
  f'moved between molecules, which parameterization does not intend.')
884
896
  return charged
885
897
 
898
+ def _report_overlong_bonds(self, when, limit=0.2, show=5):
899
+ """Logs any bond too long to be a bond in the structure being handed on.
900
+
901
+ A crosslinked network can finish a build carrying a bond stretched far past what
902
+ chemistry allows, and nothing else reports it: the topology is valid, every
903
+ molecule is neutral, and the run completes. htpolynet-study measured a C-C at
904
+ 3.20 A in two of five *final* structures, unchanged to two decimals by a 160 ps
905
+ anneal -- a monomer held stretched by network tension from a ring closure it was
906
+ not part of. Ring bonds themselves always relaxed; these did not. Anything
907
+ computed from such a structure inherits it, so it should at least be said out
908
+ loud. See ROADMAP.md for the mechanism and why there is no fix yet.
909
+
910
+ Lengths use the minimum-image convention, so a bond spanning a periodic boundary
911
+ is measured across the boundary rather than counted as long.
912
+
913
+ Args:
914
+ when (str): stage label for the message, e.g. 'in final'
915
+ limit (float): longest credible bond, in nm. The longest ordinary single
916
+ bond between light elements is C-S at about 0.182 nm, so 0.2 is
917
+ generous: this is meant to catch a bond that is not a bond any more,
918
+ not to police a strained one.
919
+ show (int): how many of the worst to name individually
920
+
921
+ Returns:
922
+ pandas.DataFrame: the offending bonds, longest first
923
+ """
924
+ TC = self.TopoCoord
925
+ D = getattr(getattr(TC, 'Topology', None), 'D', None) or {}
926
+ bonds = D.get('bonds')
927
+ if bonds is None or bonds.empty:
928
+ return pd.DataFrame()
929
+ work = bonds[['ai', 'aj']].copy()
930
+ TC.add_length_attribute(work, attr_name='length')
931
+ long = work[work['length'] > limit].sort_values('length', ascending=False)
932
+ if long.empty:
933
+ logger.info(f'Bond lengths {when}: no bond among {work.shape[0]} exceeds {limit} nm')
934
+ return long
935
+ A = TC.Coordinates.A.set_index('globalIdx')
936
+
937
+ def label(i):
938
+ try:
939
+ r = A.loc[int(i)]
940
+ return f'{r.atomName}({int(i)}) of {r.resName}{int(r.resNum)}'
941
+ except Exception:
942
+ return str(int(i))
943
+
944
+ ess = '' if long.shape[0] == 1 else 's'
945
+ worst = '; '.join(f'{label(r.ai)}-{label(r.aj)} at {r.length * 10:.2f} A'
946
+ for r in long.head(show).itertuples())
947
+ logger.warning(f'Bond lengths {when}: {long.shape[0]} bond{ess} of {work.shape[0]} exceed '
948
+ f'{limit} nm, which is longer than any real bond between these elements. '
949
+ f'Worst: {worst}. A bond this long survives minimization and annealing -- '
950
+ f'it is held by the surrounding network, not by thermal motion -- and every '
951
+ f'property computed from this structure carries it. See ROADMAP.md.')
952
+ return long
953
+
886
954
  def _write_vmd_viz_files(self, result_name='final'):
887
955
  """Writes a PSF (real bond topology for VMD) and a TCL helper that
888
956
  trims bonds spanning periodic boundaries so VMD doesn't render the