htpolynet 2.7.0__tar.gz → 2.8.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 (348) hide show
  1. htpolynet-2.8.0/.github/workflows/docs.yml +90 -0
  2. {htpolynet-2.7.0 → htpolynet-2.8.0}/.github/workflows/release.yaml +30 -6
  3. {htpolynet-2.7.0 → htpolynet-2.8.0}/.gitignore +3 -0
  4. {htpolynet-2.7.0 → htpolynet-2.8.0}/CHANGELOG.md +159 -0
  5. {htpolynet-2.7.0 → htpolynet-2.8.0}/PKG-INFO +2 -1
  6. {htpolynet-2.7.0 → htpolynet-2.8.0}/ROADMAP.md +236 -28
  7. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/run.rst +4 -1
  8. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/run.rst +2 -1
  9. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +1 -1
  10. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +14 -12
  11. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +1 -1
  12. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +7 -6
  13. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +56 -75
  14. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/run.rst +12 -8
  15. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/index.rst +11 -0
  16. htpolynet-2.8.0/docs/source/index.rst +71 -0
  17. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/configs/configs-for-analyze.rst +2 -2
  18. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/configs/configs-for-run.rst +25 -2
  19. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/index.rst +1 -0
  20. htpolynet-2.8.0/docs/source/user-guide/periodic-networks.rst +137 -0
  21. {htpolynet-2.7.0 → htpolynet-2.8.0}/pyproject.toml +3 -2
  22. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/check-conda-sync.py +86 -22
  23. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/configuration.py +55 -2
  24. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/topocoord.py +92 -6
  25. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/topology.py +11 -2
  26. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cure/curecontroller.py +5 -1
  27. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +3 -0
  28. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +3 -0
  29. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +3 -0
  30. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +3 -0
  31. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +3 -0
  32. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +3 -0
  33. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +3 -0
  34. htpolynet-2.8.0/src/htpolynet/schema/base.yaml +936 -0
  35. htpolynet-2.8.0/src/htpolynet/utils/convergence.py +163 -0
  36. htpolynet-2.8.0/tests/unit/test_conda_sync.py +131 -0
  37. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_configuration.py +166 -19
  38. htpolynet-2.8.0/tests/unit/test_convergence.py +155 -0
  39. htpolynet-2.8.0/tests/unit/test_density_gate.py +108 -0
  40. htpolynet-2.8.0/tests/unit/test_moleculetype_name.py +56 -0
  41. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_relax_instrumentation.py +18 -0
  42. htpolynet-2.7.0/docs/source/index.rst +0 -38
  43. htpolynet-2.7.0/docs/source/release-history.rst +0 -69
  44. {htpolynet-2.7.0 → htpolynet-2.8.0}/.claude/settings.json +0 -0
  45. {htpolynet-2.7.0 → htpolynet-2.8.0}/.claude/skills/htpolynet/SKILL.md +0 -0
  46. {htpolynet-2.7.0 → htpolynet-2.8.0}/.envrc +0 -0
  47. {htpolynet-2.7.0 → htpolynet-2.8.0}/.github/workflows/conda-forge-sync.yml +0 -0
  48. {htpolynet-2.7.0 → htpolynet-2.8.0}/.github/workflows/docker.yml +0 -0
  49. {htpolynet-2.7.0 → htpolynet-2.8.0}/.github/workflows/test.yml +0 -0
  50. {htpolynet-2.7.0 → htpolynet-2.8.0}/.readthedocs.yaml +0 -0
  51. {htpolynet-2.7.0 → htpolynet-2.8.0}/CITATION.cff +0 -0
  52. {htpolynet-2.7.0 → htpolynet-2.8.0}/CLAUDE.md +0 -0
  53. {htpolynet-2.7.0 → htpolynet-2.8.0}/LICENSE +0 -0
  54. {htpolynet-2.7.0 → htpolynet-2.8.0}/MANIFEST.in +0 -0
  55. {htpolynet-2.7.0 → htpolynet-2.8.0}/README.md +0 -0
  56. {htpolynet-2.7.0 → htpolynet-2.8.0}/docker/Dockerfile +0 -0
  57. {htpolynet-2.7.0 → htpolynet-2.8.0}/docker/compose.yml +0 -0
  58. {htpolynet-2.7.0 → htpolynet-2.8.0}/docker/docker-entrypoint.sh +0 -0
  59. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/Makefile +0 -0
  60. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/README.rst +0 -0
  61. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/make.bat +0 -0
  62. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/requirements.txt +0 -0
  63. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/_static/.gitkeep +0 -0
  64. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/changelog.rst +0 -0
  65. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/conf.py +0 -0
  66. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
  67. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
  68. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
  69. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
  70. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
  71. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
  72. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
  73. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
  74. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
  75. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
  76. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
  77. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
  78. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  79. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  80. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  81. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  82. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  83. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
  84. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  85. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  86. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  87. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
  88. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
  89. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
  90. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
  91. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
  92. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
  93. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
  94. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
  95. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
  96. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
  97. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  98. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  99. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  100. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
  101. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
  102. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
  103. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
  104. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  105. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  106. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  107. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
  108. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  109. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
  110. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
  111. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
  112. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
  113. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
  114. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
  115. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
  116. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
  117. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
  118. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
  119. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
  120. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
  121. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
  122. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
  123. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  124. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  125. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  126. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
  127. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  128. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  129. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  130. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
  131. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
  132. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
  133. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
  134. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
  135. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
  136. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
  137. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
  138. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
  139. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
  140. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
  141. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
  142. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  143. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
  144. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
  145. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
  146. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
  147. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
  148. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
  149. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
  150. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
  151. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
  152. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
  153. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
  154. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  155. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  156. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  157. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
  158. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  159. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  160. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  161. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  162. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
  163. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
  164. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
  165. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
  166. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
  167. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  168. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  169. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  170. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
  171. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  172. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  173. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  174. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  175. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
  176. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
  177. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
  178. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
  179. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
  180. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
  181. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
  182. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
  183. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  184. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  185. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  186. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  187. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  188. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  189. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  190. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +0 -0
  191. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
  192. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
  193. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/htpolynetpackage.rst +0 -0
  194. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/install.rst +0 -0
  195. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/references/index.rst +0 -0
  196. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/references/mol2-reference.pdf +0 -0
  197. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/references.bib +0 -0
  198. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/CURE.odg +0 -0
  199. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/bond_filter.odg +0 -0
  200. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/building-a-system.rst +0 -0
  201. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  202. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/configuration-files.rst +0 -0
  203. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/container-usage.rst +0 -0
  204. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/flow1.odg +0 -0
  205. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/flow1yaml.odg +0 -0
  206. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/hydrogenated.eps +0 -0
  207. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/hydrogenated.fig +0 -0
  208. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
  209. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/STY.png +0 -0
  210. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/STYCC.png +0 -0
  211. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  212. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
  213. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  214. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  215. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  216. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  217. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  218. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/postcure-repair.rst +0 -0
  219. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/program-flow.rst +0 -0
  220. {htpolynet-2.7.0 → htpolynet-2.8.0}/docs/source/user-guide/usage.rst +0 -0
  221. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/release.sh +0 -0
  222. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/render-detail.sh +0 -0
  223. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/render-detail.tcl +0 -0
  224. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/render-snapshot.sh +0 -0
  225. {htpolynet-2.7.0 → htpolynet-2.8.0}/scripts/run_all_examples.sh +0 -0
  226. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/__init__.py +0 -0
  227. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/analysis/__init__.py +0 -0
  228. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/analysis/analyze.py +0 -0
  229. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/analysis/plot.py +0 -0
  230. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/analysis/postsim.py +0 -0
  231. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/analysis/utils.py +0 -0
  232. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cli.py +0 -0
  233. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/__init__.py +0 -0
  234. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/bondtemplate.py +0 -0
  235. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/coordinates.py +0 -0
  236. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/molecule.py +0 -0
  237. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/paramcache.py +0 -0
  238. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/projectfilesystem.py +0 -0
  239. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/core/runtime.py +0 -0
  240. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cure/__init__.py +0 -0
  241. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cure/chain.py +0 -0
  242. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cure/expandreactions.py +0 -0
  243. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/cure/reaction.py +0 -0
  244. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/__init__.py +0 -0
  245. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/ambertools.py +0 -0
  246. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/command.py +0 -0
  247. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/gromacs.py +0 -0
  248. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/slurm.py +0 -0
  249. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/smiles_input.py +0 -0
  250. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/external/software.py +0 -0
  251. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/__init__.py +0 -0
  252. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/bondlist.py +0 -0
  253. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/lattice.py +0 -0
  254. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/linkcell.py +0 -0
  255. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/matrix4.py +0 -0
  256. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/geometry/ring.py +0 -0
  257. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/io/__init__.py +0 -0
  258. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/io/gro.py +0 -0
  259. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/io/mol2.py +0 -0
  260. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/io/pdb.py +0 -0
  261. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/repair/__init__.py +0 -0
  262. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/repair/cyanate_cap.py +0 -0
  263. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/repair/topology_surgery.py +0 -0
  264. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/README.md +0 -0
  265. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/__init__.py +0 -0
  266. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/claude/SKILL.md +0 -0
  267. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/README.md +0 -0
  268. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  269. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  270. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  271. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
  272. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  273. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  274. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  275. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  276. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  277. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  278. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  279. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  280. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  281. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  282. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  283. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  284. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  285. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
  286. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  287. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  288. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  289. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  290. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  291. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  292. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  293. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  294. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  295. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
  296. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  297. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  298. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  299. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
  300. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
  301. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  302. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  303. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
  304. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/__init__.py +0 -0
  305. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/banner.py +0 -0
  306. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/checkpoint.py +0 -0
  307. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/dataframetools.py +0 -0
  308. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/inputcheck.py +0 -0
  309. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/logsetup.py +0 -0
  310. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/profiling.py +0 -0
  311. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/stringthings.py +0 -0
  312. {htpolynet-2.7.0 → htpolynet-2.8.0}/src/htpolynet/utils/vmd_viz.py +0 -0
  313. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/__init__.py +0 -0
  314. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/conftest.py +0 -0
  315. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/__init__.py +0 -0
  316. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/config1.gro +0 -0
  317. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/config1.top +0 -0
  318. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/config2.gro +0 -0
  319. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/config2.top +0 -0
  320. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/items31.edr +0 -0
  321. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/items43.edr +0 -0
  322. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/items45.edr +0 -0
  323. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/fixtures/short.mdp +0 -0
  324. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_bondtemplate.py +0 -0
  325. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_cap_placement.py +0 -0
  326. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_chain.py +0 -0
  327. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_completion_bias.py +0 -0
  328. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_dataframetools.py +0 -0
  329. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_gpu_usability.py +0 -0
  330. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
  331. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
  332. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_inputcheck.py +0 -0
  333. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_linkcell_pierce.py +0 -0
  334. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_paramcache.py +0 -0
  335. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_paramcache_ambertools.py +0 -0
  336. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_parameterize_react.py +0 -0
  337. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_plot_smoke.py +0 -0
  338. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_projectfilesystem.py +0 -0
  339. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_repair_conversion.py +0 -0
  340. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_resources.py +0 -0
  341. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_ring.py +0 -0
  342. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_ring_pierce_figs.py +0 -0
  343. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_setup_claude.py +0 -0
  344. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_slurm_script.py +0 -0
  345. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_smiles_input.py +0 -0
  346. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_software_provenance.py +0 -0
  347. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_topology/test.top +0 -0
  348. {htpolynet-2.7.0 → htpolynet-2.8.0}/tests/unit/test_topology.py +0 -0
@@ -0,0 +1,90 @@
1
+ name: Docs
2
+
3
+ # ReadTheDocs has no webhook on this repository. Its only trigger was the
4
+ # "Trigger ReadTheDocs build" step in release.yaml, which fires on v* tags, so
5
+ # the published docs tracked *releases* rather than main: a docs-only commit
6
+ # did not appear on RTD until the next release. This workflow closes that gap
7
+ # for the `latest` version. `stable` follows tags and stays release.yaml's job.
8
+ #
9
+ # The build job also enforces the repo invariant that the docs build with zero
10
+ # warnings (-W). RTD builds without -W, so a warning introduced on main would
11
+ # otherwise publish green and be caught only by whoever next built locally.
12
+ # Gating the trigger on that build means a broken docs commit is never pushed
13
+ # to RTD.
14
+
15
+ on:
16
+ push:
17
+ branches: [main]
18
+ paths:
19
+ # autodoc reads docstrings and the tutorials literalinclude the example
20
+ # configs, so src/ is a docs input; changelog.rst includes CHANGELOG.md;
21
+ # RTD pip-installs the package, so pyproject.toml matters too.
22
+ - 'docs/**'
23
+ - 'src/**'
24
+ - 'CHANGELOG.md'
25
+ - '.readthedocs.yaml'
26
+ - 'pyproject.toml'
27
+ - '.github/workflows/docs.yml'
28
+ pull_request:
29
+ paths:
30
+ - 'docs/**'
31
+ - 'src/**'
32
+ - 'CHANGELOG.md'
33
+ - '.readthedocs.yaml'
34
+ - 'pyproject.toml'
35
+ - '.github/workflows/docs.yml'
36
+ workflow_dispatch:
37
+
38
+ concurrency:
39
+ group: docs-${{ github.ref }}
40
+ cancel-in-progress: true
41
+
42
+ jobs:
43
+ build:
44
+ name: build (zero warnings)
45
+ runs-on: ubuntu-latest
46
+ steps:
47
+ - uses: actions/checkout@v4
48
+
49
+ - name: Install uv
50
+ uses: astral-sh/setup-uv@v5
51
+
52
+ # Same invocation as CLAUDE.md documents for local use. -W turns
53
+ # warnings into errors; -a rebuilds everything so a warning cannot be
54
+ # skipped by an up-to-date doctree.
55
+ - name: Build docs
56
+ run: >
57
+ uv run --with-requirements docs/requirements.txt --with sphinx
58
+ python -m sphinx -b html -W -a docs/source _docbuild
59
+
60
+ trigger-rtd:
61
+ name: trigger ReadTheDocs
62
+ needs: build
63
+ if: github.event_name != 'pull_request'
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - name: Trigger ReadTheDocs build of latest
67
+ env:
68
+ RTD_SECRET: ${{ secrets.RTD_SECRET }}
69
+ run: |
70
+ set -euo pipefail
71
+ if [ -z "${RTD_SECRET:-}" ]; then
72
+ echo "::error::RTD_SECRET is not set; cannot trigger a ReadTheDocs build."
73
+ exit 1
74
+ fi
75
+ # curl exits 0 on a 4xx unless told otherwise, so check the status
76
+ # explicitly. A trigger that fails silently is worse than none: the
77
+ # job goes green and the docs quietly stop updating.
78
+ code=$(curl -sS --max-time 60 -o rtd-response.json -w '%{http_code}' \
79
+ -X POST \
80
+ -H "Authorization: Token ${RTD_SECRET}" \
81
+ https://readthedocs.org/api/v3/projects/htpolynet/versions/latest/builds/)
82
+ echo "ReadTheDocs returned HTTP ${code}"
83
+ cat rtd-response.json || true
84
+ echo
85
+ case "${code}" in
86
+ 2*) echo "Build of 'latest' queued." ;;
87
+ 401|403) echo "::error::RTD rejected the token (HTTP ${code}); RTD_SECRET is missing, wrong or expired."; exit 1 ;;
88
+ 404) echo "::error::RTD has no project 'htpolynet' or no version 'latest' (HTTP 404)."; exit 1 ;;
89
+ *) echo "::error::RTD returned HTTP ${code}."; exit 1 ;;
90
+ esac
@@ -79,13 +79,37 @@ jobs:
79
79
  path: dist/
80
80
 
81
81
  - name: Trigger ReadTheDocs build
82
+ env:
83
+ RTD_SECRET: ${{ secrets.RTD_SECRET }}
84
+ RTD_VERSION: ${{ github.ref_name }}
82
85
  run: |
83
- curl -X POST \
84
- -H "Authorization: Token ${{ secrets.RTD_SECRET }}" \
85
- https://readthedocs.org/api/v3/projects/htpolynet/versions/latest/builds/
86
- curl -X POST \
87
- -H "Authorization: Token ${{ secrets.RTD_SECRET }}" \
88
- https://readthedocs.org/api/v3/projects/htpolynet/versions/${{ github.ref_name }}/builds/
86
+ set -euo pipefail
87
+ if [ -z "${RTD_SECRET:-}" ]; then
88
+ echo "::error::RTD_SECRET is not set; cannot trigger a ReadTheDocs build."
89
+ exit 1
90
+ fi
91
+ # curl exits 0 on a 4xx unless told otherwise. These calls used to
92
+ # go unchecked, so an expired token would print a 401 body and the
93
+ # step would still pass -- the docs would just stop updating.
94
+ trigger() {
95
+ local version="$1"
96
+ local code
97
+ code=$(curl -sS --max-time 60 -o rtd-response.json -w '%{http_code}' \
98
+ -X POST \
99
+ -H "Authorization: Token ${RTD_SECRET}" \
100
+ "https://readthedocs.org/api/v3/projects/htpolynet/versions/${version}/builds/")
101
+ echo "ReadTheDocs (${version}) returned HTTP ${code}"
102
+ cat rtd-response.json || true
103
+ echo
104
+ case "${code}" in
105
+ 2*) return 0 ;;
106
+ *) echo "::error::RTD returned HTTP ${code} for version '${version}'."; return 1 ;;
107
+ esac
108
+ }
109
+ trigger latest
110
+ # The tag's own version may not exist yet if RTD has not synced it;
111
+ # that is not a release failure, so report it without failing the job.
112
+ trigger "${RTD_VERSION}" || echo "::warning::Could not trigger the '${RTD_VERSION}' version build; trigger it from the RTD dashboard if that version is expected."
89
113
 
90
114
  publish:
91
115
  needs: release
@@ -145,3 +145,6 @@ dmypy.json
145
145
  .pyre/
146
146
  .vscode/settings.json
147
147
 
148
+
149
+ # sphinx output from the docs CI job (and local runs that mirror it)
150
+ _docbuild/
@@ -7,6 +7,127 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.8.0] - 2026-09-12
11
+
12
+ ### Added
13
+
14
+ - **Configuration files are now validated.** `htpolynet run` checks every
15
+ configuration against a schema before doing anything else, and fills in
16
+ every documented default from that same schema. Previously a configuration
17
+ was read by picking out the keys htpolynet recognized and silently discarding
18
+ the rest, so a misspelled key did nothing and said nothing: a
19
+ `desired_converson: 0.9` typo produced a default-value build -- a half-cure --
20
+ with no message. Errors now name the offending location, for example
21
+ `Attribute 'smilse' invalid ... under 'constituents[STY]'` or
22
+ `Attribute 'stage' of 'reactions[1]' must be one of build, param, cure, cap,
23
+ repair`. Validation covers every section, including molecule records,
24
+ reactions and postcure repair specs; only `gromacs.mdrun_options` is left
25
+ open on purpose. This adds a runtime dependency on
26
+ [ycleptic](https://pypi.org/project/ycleptic/) 2.4.1 or later.
27
+
28
+ - **Densification can gate on measured density convergence instead of a fixed
29
+ step count.** An NPT record in `densification.equilibration` may carry a
30
+ `converge` block; the stage then repeats until the density settles or a
31
+ ceiling is hit. It is off unless configured, so existing configurations
32
+ reproduce exactly. The criterion is an autocorrelation-corrected standard
33
+ error, `sigma/sqrt(N/tau_int)` -- an NPT cell density is correlated over
34
+ hundreds of steps, so successive frames are not independent samples and a
35
+ naive standard error is optimistic by roughly 1.5x, which would stop the
36
+ gate early. It also makes the tolerance size-aware for free. A small
37
+ standard error alone is not accepted as convergence, because a trace that is
38
+ still climbing looks tight in every short window; the window's two halves
39
+ are compared as well. **Reaching the ceiling is reported as a failure**,
40
+ with a warning saying the number is an unsettled box rather than the
41
+ system's density.
42
+
43
+ Densification is the one place this belongs: the 200 to ~1100 kg/m^3
44
+ compaction happens once and involves a large volume change. Gating the CURE
45
+ relaxation loop was measured and rejected -- past the gel point the
46
+ unreacted species are bonded into the network and topologically constrained,
47
+ the effective diffusion exponent falls to about 0.14, and restoring the
48
+ mobility a gate would wait for takes of order 10^4 times the relaxation
49
+ time. Note also that the gate certifies convergence of the Berendsen
50
+ barostat `npt.mdp` currently uses, which does not sample a correct NPT
51
+ ensemble; treat it as a reproducibility criterion, not a physical one.
52
+
53
+ ### Changed
54
+
55
+ - **A configuration that 2.7.0 accepted may now be rejected.** This is the
56
+ point of the validation above, but it is a change in behavior: a key
57
+ htpolynet does not know, a value of the wrong type, a value outside its
58
+ allowed choices, or a missing required field now stops the run with a
59
+ message instead of being ignored. Every shipped example validates. If an
60
+ existing configuration of yours is rejected, the message says where; the fix
61
+ is almost always a misspelled or obsolete key that was already having no
62
+ effect.
63
+
64
+ - **Every shipped example now gates its densification on density
65
+ convergence**, using the `converge` block described under Added, so their
66
+ densification stages run until the box settles rather than for a fixed
67
+ duration.
68
+
69
+ - **The conda-forge package for this release will follow later.** ycleptic,
70
+ the new dependency, is not yet available on conda-forge, so the conda-forge
71
+ build of this version cannot be published until it is. In the meantime the
72
+ release is available from PyPI (`pip install htpolynet`) and in the container
73
+ image (`ghcr.io/cameronabrams/htpolynet`); conda-forge users will stay on
74
+ 2.7.0 until then.
75
+
76
+ - **The single moleculetype htpolynet writes is now named `whole_system`, not
77
+ `None`.** An entire build is written as one moleculetype on purpose -- a
78
+ cured network is one covalently connected molecule -- but the default name
79
+ was the literal string `None`, which reads like an unset field or a bug. It
80
+ sits on exactly the line users inspect after GROMACS warns about
81
+ "inconsistent shifts", so it was sending them looking for a topology error
82
+ that is not there. Purely cosmetic: GROMACS accepts either, and existing
83
+ topologies that say `None` still read back unchanged.
84
+
85
+ ### Fixed
86
+
87
+ - **A config that omitted `CURE.relax.increment` crashed at the first
88
+ relax.** The default was `0.0`, and `_distance_attenuation` derives its
89
+ stage count as `int(maxL/increment)` with no guard, so the build died with
90
+ `ZeroDivisionError` rather than any message about the config. The
91
+ documented default -- 0.08 -- is now the actual one. Dragging's `increment`
92
+ stays 0.0, which is a sentinel rather than the same bug: its own 0.0 `limit`
93
+ disables dragging before anything divides. Every shipped example sets
94
+ `relax.increment` explicitly, which is why this went unnoticed.
95
+
96
+ ### Documentation
97
+
98
+ - **New page: analyzing trajectories of periodic networks.** Explains why
99
+ `gmx trjconv -pbc whole` reports "There were N inconsistent shifts" on a
100
+ cured network (the bond graph wraps through the periodic boundaries, so no
101
+ consistent unwrapped image exists), and that this is expected rather than a
102
+ topology error -- on example 3 the count is zero until the network
103
+ percolates, then 2 at 69% conversion and 140 at 95%. It gives tested recipes
104
+ for visualization, MSD and free volume. The MSD one carries a real
105
+ warning: `gmx msd`'s default `-rmpbc` tries to make the network whole every
106
+ frame and silently inflates the MSD, by about 2.4x at 100 ps on example 3,
107
+ while still exiting normally; use `-pbc nojump` and then `-normpbc`. Prompted
108
+ by a user report.
109
+
110
+ - The `htpolynet analyze` free-volume docs now say that the per-molecule lines
111
+ in `gmx freevolume`'s output describe the whole box as one molecule, and two
112
+ instances of `poststim` now read `postsim`.
113
+
114
+ - **The docs landing page carries the standard badge row, and the release
115
+ history is gone from the table of contents.** `release-history.rst`
116
+ duplicated what this file already records from 1.0.8 forward, so it is
117
+ deleted and `changelog` moves to the *end* of the contents tree rather than
118
+ sitting second. The seven pre-1.0.8 entries it held -- 1.0.7.2 back to
119
+ 0.0.1, which this file did not cover -- were migrated here first, so nothing
120
+ is lost by the deletion. The landing page now shows the same eight badges
121
+ as the README: tests, PyPI, conda-forge, Python versions, license, docs,
122
+ downloads and DOI.
123
+
124
+ - **Two more `CURE`/`densification` defaults in the config tables were
125
+ wrong.** `densification.initial_density` is 200.0 kg/m^3, not the 300.0 the
126
+ table gave; and the prose under `min_allowable_bondcycle_length` still said
127
+ "setting it to zero (the default)" after the table had been corrected to -1.
128
+ Found while transcribing the defaults into a machine-readable schema, which
129
+ is the point of doing so.
130
+
10
131
  ## [2.7.0] - 2026-09-08
11
132
 
12
133
  ### Changed
@@ -1018,3 +1139,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1018
1139
  ### Changed
1019
1140
 
1020
1141
  - Uses `chordless_cycles` to find rings; `ringidx` is no longer a unique atom attribute; improved ring-pierce detection.
1142
+
1143
+ ## [1.0.7.2] - untagged
1144
+
1145
+ ### Changed
1146
+
1147
+ - Moved the Library package to the `resources` subpackage of `htpolynet`.
1148
+
1149
+ ## [1.0.6] - 2023-06-21
1150
+
1151
+ ### Added
1152
+
1153
+ - `gmx`-style `analyze` subcommand.
1154
+
1155
+ ## [1.0.5] - 2022-09-29
1156
+
1157
+ ### Added
1158
+
1159
+ - Post-build MD simulations and plotting functionality.
1160
+
1161
+ ## [1.0.2] - 2022-09-16
1162
+
1163
+ ### Changed
1164
+
1165
+ - Enhanced molecule-network graph drawing in the `plot` subcommand.
1166
+
1167
+ ## [1.0.1] - 2022-09-07
1168
+
1169
+ ### Fixed
1170
+
1171
+ - Atom index assignment for systems with more than 100,000 atoms.
1172
+
1173
+ ## [1.0.0] - 2022-09-03
1174
+
1175
+ - First release.
1176
+
1177
+ ## [0.0.1] - 2022-08-29
1178
+
1179
+ - Initial beta version.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: htpolynet
3
- Version: 2.7.0
3
+ Version: 2.8.0
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/
@@ -26,6 +26,7 @@ Requires-Dist: rdkit>=2024.3
26
26
  Requires-Dist: requests>=2.28
27
27
  Requires-Dist: scipy>=1.10
28
28
  Requires-Dist: setuptools
29
+ Requires-Dist: ycleptic>=2.4.1
29
30
  Provides-Extra: dev
30
31
  Requires-Dist: pytest; extra == 'dev'
31
32
  Provides-Extra: test
@@ -110,6 +110,24 @@ Coverage as of the last measurement: **38.8%** overall.
110
110
 
111
111
  ## Release and distribution
112
112
 
113
+ - **The conda recipe drops `matplotlib`'s version floor.** `pyproject.toml`
114
+ requires `matplotlib>=3.5`; the feedstock recipe lists a bare
115
+ `matplotlib-base` with no lower bound, so conda can solve an environment
116
+ pip would refuse. Found by grayskull's dependency analysis on feedstock
117
+ PR #21, not by us -- `check-conda-sync.py` compared names with the version
118
+ specifiers stripped and so could not see a floor at all (fixed 2026-09-09;
119
+ it now compares floors, and reports this one). Practical risk is low
120
+ because `analysis/plot.py`'s `_get_cmap` carries a pre-3.5 fallback, but
121
+ the declaration should match. **Fold it into the hand-written feedstock PR
122
+ that has to add `ycleptic >=2.4.1` anyway** rather than opening a separate
123
+ one -- same file, two lines.
124
+
125
+ Three other items in that same grayskull report are noise and should not be
126
+ "fixed": `python {{ python_min }}` vs `python 3.10` is a Jinja rendering
127
+ artifact, `rdkit >=2024.03` vs `>=2024.3` are the same version to both
128
+ conda and pip, and `ambertools`/`graphviz` are deliberate conda-only
129
+ additions with no PyPI equivalent.
130
+
113
131
  - **The release preflight cannot tell whether the *previous* release
114
132
  actually shipped to conda-forge.** `scripts/check-conda-sync.py` compares
115
133
  `pyproject.toml`'s runtime deps against the feedstock recipe, which
@@ -575,28 +593,6 @@ Coverage as of the last measurement: **38.8%** overall.
575
593
  The densification entry below is the same shape of problem -- a number
576
594
  computed once and trusted thereafter.
577
595
 
578
- - **If anything gates on density convergence, it should be densification,
579
- not cure.** The initial 200 -> ~1100 kg/m3 compaction is one-shot,
580
- involves a large volume change, and currently runs on fixed `nsteps`
581
- (`runtime_defaults['densification']['equilibration']`,
582
- `core/runtime.py:78-86`). That is the direct analogue of pestifer's use of
583
- `density_equilibrate` -- a terminal, run-until-converged replacement for a
584
- hand-written NPT ladder -- and it is cheap, because it happens once per
585
- build rather than ~10 times.
586
-
587
- What to port from `pestifer/util/density_convergence.py` is only the
588
- criterion: an **autocorrelation-corrected SEM**, `sigma/sqrt(N/tau_int)`,
589
- because NPT cell density is autocorrelated over hundreds of steps and a
590
- naive block-means SEM is optimistic by ~1.5x. That also makes the test
591
- size-aware for free, since `sigma/mean ~ 1/sqrt(N_atoms)` while tau is
592
- roughly size-independent. Port the explicit **ceiling outcome** too, so a
593
- build that never settled says so instead of silently reporting a density.
594
- Do **not** port the chunking (`next_chunk_steps`, `is_patch_grid_crash`):
595
- that exists because NAMD fixes its patch/PME grid at the start of each
596
- `run`, and GROMACS rescales the box within one `mdrun` without that
597
- failure mode. The chunking is most of pestifer's complexity and none of
598
- its value here.
599
-
600
596
  - **Decided against: gating and extending `CURE.relax` on density
601
597
  convergence.** Raised by Cameron 2026-09-05 from the observation that
602
598
  pestifer has a gate system htpolynet does not; recommended by the study
@@ -637,12 +633,27 @@ Coverage as of the last measurement: **38.8%** overall.
637
633
  iteration and report "may not have settled", correctly, with nothing to be
638
634
  done about it. It detects a condition it cannot cure.
639
635
 
640
- **The limit on that argument:** arrest is inferred partly from gelation
641
- physics, not purely measured. The study's displacement trace is still
642
- falling at the last cure iteration, 4.63 -> 4.08 -> 3.72 A -- consistent
643
- with approaching arrest, but not a demonstrated plateau. Measuring the
644
- plateau directly would settle it either way, and is a smaller experiment
645
- than powering R16 up.
636
+ **That limit is now closed, and the conclusion is stronger than it was.**
637
+ The argument used to lean partly on gelation physics rather than
638
+ measurement. 32 cure-only builds at the production window (study session,
639
+ 2026-09-08) measure the effective diffusion exponent directly:
640
+ displacement ~ t^alpha, with alpha **0.32** at the start of cure -- already
641
+ sub-Fickian, which is 0.50 -- falling to **0.14** at the end. At alpha 0.14,
642
+ restoring the displacement a gate would need takes **3.6e4 times** the
643
+ relaxation time. That is not expensive, it is impossible, and it does not
644
+ depend on the earlier n = 4 result at all.
645
+
646
+ **And the shipped window never satisfies Varshney's criterion, not even at
647
+ the start.** Mean crossing fraction is **0.61 at iteration 1** and **0.036
648
+ at the last** -- so the window is outside the criterion it was sized against
649
+ for the whole cure, not merely late in it. This is the calibration for the
650
+ mobility report that shipped in v2.7.0: its 25 % warning threshold sits
651
+ between those two numbers, so a default build stays quiet early and warns
652
+ through the second half. Whether 25 % is the right line is not yet
653
+ established -- nothing measures what crossing fraction a *trustworthy* build
654
+ needs, only what the current one delivers -- so the threshold is a placeholder
655
+ chosen to be quiet at iteration 1, and should be revisited against a build
656
+ whose bonds are known to be well sampled.
646
657
 
647
658
  **And a structural mismatch.** Pestifer uses `density_equilibrate` as a
648
659
  terminal, one-shot replacement for a hand-written NPT ladder at the end of
@@ -735,6 +746,165 @@ Coverage as of the last measurement: **38.8%** overall.
735
746
  session's too, and it is the one of the three that has already been
736
747
  published in our documentation. Verify it first if any of them.
737
748
 
749
+ ## Configuration
750
+
751
+ - **Move config handling onto ycleptic.** Approved by Cameron 2026-09-08.
752
+ `core/configuration.py` (85 lines) reads YAML/JSON and `.get()`s eleven
753
+ known top-level sections into attributes with **no validation at all**: an
754
+ unrecognized section or a misspelled key is silently discarded. Defaults
755
+ live in three separate Python dicts applied by three hand-rolled mechanisms
756
+ at three different depths -- `Runtime.runtime_defaults` (shallow, one level,
757
+ `core/runtime.py:177`), `CureController.curedict_defaults` (two levels,
758
+ `cure/curecontroller.py:299-304`), and `Runtime.default_edict` (ad hoc). And
759
+ 937 lines of hand-maintained RST document those defaults, which is why six
760
+ of them had drifted from the code by the time anyone checked.
761
+
762
+ `src/htpolynet/schema/base.yaml` now holds the schema for the sections
763
+ ycleptic 2.3.0 can express. It is **inert**: nothing reads it, and
764
+ `pyproject.toml` does not declare a ycleptic dependency. All seven shipped
765
+ example configs validate against it, and a `desired_converson` typo that
766
+ htpolynet accepts silently today is rejected with the list of valid keys.
767
+
768
+ Staging, agreed with the ycleptic session:
769
+
770
+ 1. **ycleptic to conda-forge** -- gates shipping and nothing else, and is
771
+ now the ONLY thing gating it.
772
+ `api.anaconda.org/package/conda-forge/ycleptic` was 404 while htpolynet
773
+ is 200, and a conda package's run-deps must exist in the channel, so
774
+ declaring the dependency would make htpolynet's feedstock unbuildable and
775
+ trip `scripts/release.sh`'s `check-conda-sync.py --strict` preflight.
776
+ Submitted 2026-09-08 with Cameron's direct approval as
777
+ conda-forge/staged-recipes#34763, "Adding ycleptic"; still open, not
778
+ merged, and `api.anaconda.org/package/conda-forge/ycleptic` is still 404.
779
+
780
+ **That PR pins 2.3.0, and 2.4.0 is now out on PyPI.** As written, merging
781
+ it creates a feedstock one version behind, and 2.4.0 then arrives only
782
+ through an autotick-bot PR -- the exact cycle whose stalling is the
783
+ central OBSERVED failure in Cameron's conda-forge skill. Updating the
784
+ staged recipe to 2.4.0 before it merges would skip that cycle entirely.
785
+ It is ycleptic's PR, not ours, and this is recorded as an observation
786
+ rather than an action.
787
+ 2. **Three ycleptic grammar additions**: `value_attributes:` + `key_text:`
788
+ for free-key mappings, `value_type:` for scalar-valued ones, and
789
+ `list_defaults: replace|append` per attribute. **Released as ycleptic
790
+ 2.4.0 on PyPI**, and base.yaml uses all three.
791
+ 3. Port the flat sections and generate their reference docs -- done in
792
+ base.yaml, awaiting 1 to go live.
793
+
794
+ **The first release carrying ycleptic (2.8.0) was cut ahead of
795
+ conda-forge, deliberately.** An earlier version of this entry said a bot
796
+ PR without `ycleptic` in the recipe would be green and would ship a conda
797
+ package that fails at import, and so forbade `--skip-conda-check`. That
798
+ premise was wrong, and checked 2026-09-12: the feedstock's test runs
799
+ `htpolynet --help`, and importing `htpolynet.cli` loads ycleptic. So the
800
+ bot's PR for a ycleptic-carrying release **fails its own test**, sits red,
801
+ and cannot auto-merge. No broken conda package ships; conda-forge users
802
+ simply stay on the last good version.
803
+
804
+ What that leaves to do once ycleptic is on the channel:
805
+
806
+ a. Edit the recipe on the autotick bot's open PR for the current version
807
+ (push to the bot's fork, not to `origin` -- see the conda-forge skill)
808
+ adding `ycleptic >=2.4.1` to `run:`, and `>=3.5` to the bare
809
+ `matplotlib-base`. Its test then passes and automerge takes it.
810
+ b. If the bot has not opened one, open that recipe PR by hand.
811
+
812
+ Two cautions that still stand. The protection is the recipe's
813
+ `htpolynet --help` test; if that test is ever removed, this reasoning
814
+ stops holding and `--skip-conda-check` becomes dangerous again. And a red
815
+ bot PR must not be merged by hand -- red is the thing keeping the broken
816
+ package off the channel.
817
+ 4. Port `constituents` and `reactions`. **`constituents` is done**: it is a
818
+ `value_attributes` free-key mapping, so a typo inside a molecule record
819
+ is now rejected naming the molecule (`Attribute 'smilse' invalid ...
820
+ under 'constituents[STY]'`), `count` defaults per value, a required
821
+ `conformers.count` is enforced, and `conformers.generator.name` is
822
+ constrained to obabel/gromacs. Every list with a non-empty default
823
+ carries `list_defaults: replace`, verified to use a user's ladder
824
+ verbatim rather than appending it to the default one.
825
+
826
+ **`reactions` and `postcure_repair` are now ported too.** ycleptic 2.4.0
827
+ added `value_attributes` on a *list*, which describes multi-key records
828
+ and closed the `lwalk` gap, plus `value_type:` for scalar-valued free-key
829
+ mappings. Every config section is now validated except
830
+ `gromacs.mdrun_options`, which is deliberately open. Errors name the
831
+ offending item -- `under 'reactions[2]'`, `of 'postcure_repair[0]'`.
832
+ Today an unknown reaction key is discarded by `Reaction.__init__` with a
833
+ debug-level message, so this replaces a silent failure with a loud one.
834
+
835
+ Superseded, kept for the record -- these were the two blockers:
836
+
837
+ - ycleptic describes list items with the tagged-task idiom -- `lwalk`
838
+ takes `itemname = list(item.keys())[0]` -- and htpolynet's reaction
839
+ records are multi-key. With no schema node for the item there is
840
+ nowhere to hang `value_attributes` for `reactions[].atoms`, which
841
+ would otherwise qualify. The ycleptic session has deliberately not
842
+ changed `lwalk`; it is a real feature request.
843
+ - `value_attributes` requires every value to be a **mapping**, which
844
+ ruled out scalar-valued free-key mappings. **Closed**: `value_type:`
845
+ was bundled into ycleptic 2.4.0, and `constituents[].reactive_atoms`
846
+ and `constituents[].rename_atoms` now declare `value_type: str` and
847
+ are validated. `reactions[].reactants` (`{1: BPA, 2: HIE}`) is the
848
+ same shape and would work too, but it lives inside a `reactions` list
849
+ item, so the `lwalk` limitation above blocks it regardless.
850
+
851
+ - **`required: true` on a list attribute is silently ineffective in ycleptic
852
+ 2.4.0.** An absent required list is filled with `[]` and no error is raised
853
+ (`walkers.py:389-397`); scalars raise, and dicts raise via their required
854
+ children. Verified with a minimal spec, and it is the exact class of
855
+ do-nothing declaration `speccheck` exists to catch, which does not catch
856
+ this one. In base.yaml it means `reactions[].bonds`, `bonds[].atoms` and the
857
+ repair spec's `ring_carbon_atoms`, `ring_nitrogen_atoms` and
858
+ `reactive_oxygen_atoms` are declared required and are not enforced: omitting
859
+ one validates, then fails deeper in htpolynet. The declarations are kept
860
+ because they state the intent correctly and will start working when ycleptic
861
+ fixes it. Reported to the ycleptic session; not worked around here.
862
+
863
+ **The version floor is a trap; read this before pinning anything.** The
864
+ staged-recipes submission is necessarily at ycleptic **2.3.0**, because
865
+ staged-recipes needs a tarball that already exists. Step 3's base.yaml is
866
+ written against 2.3.0 and works there. But the free-key node step 4 needs
867
+ will land in **2.4.0**, and 2.4.0 reaches conda-forge only via an
868
+ autotick-bot PR *after* that release -- and the central OBSERVED failure in
869
+ Cameron's conda-forge skill is exactly those bot PRs sitting red for months
870
+ while conda-forge serves the stale version. So: pin `ycleptic>=2.3.0` when
871
+ step 3 goes live, and **do not raise the floor to 2.4.0 until the anaconda
872
+ API confirms 2.4.0 is actually on the channel** -- not when it is released,
873
+ not when the bot PR opens. Raising it early recreates precisely the
874
+ unbuildable-feedstock problem step 1 exists to avoid. The ycleptic session
875
+ will report when the API says so.
876
+
877
+ Two hazards are recorded in the base.yaml header rather than here, because
878
+ that is where someone editing it will look: ycleptic's `dwalk` rejects any
879
+ key not declared, so user-keyed sections must currently be bare `dict` and
880
+ are unvalidated; and a bare list's default *concatenates* rather than
881
+ replaces, so a base default of `[min, nvt, npt]` plus a user's `[nvt]`
882
+ yields `['min','nvt','npt','nvt']` silently. Every list in base.yaml
883
+ therefore declares no default, which gives correct replace semantics, with
884
+ the real default left in Python and marked.
885
+
886
+ - **Documented `CURE.drag`/`CURE.relax` defaults do not match the code, and
887
+ several keys are undocumented.** The tables give `drag.increment` 0.08 and
888
+ `drag.limit` 0.3 where `curedict_defaults` has 0.0 for both -- sentinels
889
+ that disable dragging via the `:316` guard, so the documented defaults would
890
+ turn on a stage ladder the code turns off. (`relax.increment` was the same
891
+ kind of mismatch and is now fixed in the code's favor: it defaults to the
892
+ documented 0.08. `relax.nstages: 6` is still declared and never read.)
893
+ Undocumented entirely:
894
+ `drag.trigger_distance`, `drag.kb`, `drag.nstages`, `drag.cutoff_pad`,
895
+ `relax.nstages`, `relax.cutoff_pad`, the whole `CURE.output` block,
896
+ `densification.scale`, `densification.aspect_ratio` and
897
+ `densification.initial_boxsize`. Generating the reference from base.yaml is
898
+ what makes this class of error impossible; until then the tables need a pass.
899
+
900
+ - **`resolve_type_discrepancies` is accepted in two places and documented in
901
+ one.** `core/runtime.py:326` falls back from
902
+ `cfg.gaff.get('resolve_type_discrepancies',[])` to
903
+ `cfg.resolve_type_discrepancies`, so both a top-level key and a
904
+ `GAFF`-scoped one work, with GAFF winning. The
905
+ docs describe only the GAFF-scoped form. base.yaml declares both, marking the
906
+ top-level spelling deprecated; pick one before the schema goes live.
907
+
738
908
  ## Simulation defaults
739
909
 
740
910
  - **The halogen constraint failure is fixed but not explained.** v2.7.0
@@ -951,6 +1121,44 @@ Coverage as of the last measurement: **38.8%** overall.
951
1121
  `_get_cmap()` once `matplotlib>=3.6` is a safe floor; the
952
1122
  `matplotlib.colormaps` registry is then always present.
953
1123
 
1124
+ - **The 18 postsim TODO placeholders are the last unfinished tutorial work.**
1125
+ Every one of the seven `postsim.rst` pages carries `**TODO:** insert the
1126
+ rho_v_ns.png plots`, `**TODO:** insert tg.png` and `**TODO:** report the
1127
+ fractional free volume`, and `6-cyanate-ester/monomers.rst` still wants a
1128
+ `pics/TAZ.png`. These are unfinished rather than stale: nothing in them is
1129
+ wrong, the numbers and figures were simply never produced. Filling them
1130
+ needs real compute -- `htpolynet postsim` runs, which the 2026-09-08 example
1131
+ sweep did not do, since it ran `htpolynet run` only.
1132
+
1133
+ - **Tutorial timings are hardware-dependent and nothing said so until now.**
1134
+ The stage tables in examples 4, 5 and 6 were rewritten on 2026-09-09 from
1135
+ measured 24-core runs and now say "on 24 cores". Before that, example 5's
1136
+ table quoted ~12 hours from a 16-core run of an earlier configuration of
1137
+ that example, against 3h45m measured now -- and its iteration count was 15
1138
+ against 9 measured, which is a real behavior change rather than hardware.
1139
+ Whatever replaces this should either state the machine or stop quoting
1140
+ absolute times.
1141
+
1142
+ - **`htpolynet analyze` has no MSD stage, and one would have to be written
1143
+ carefully.** A user asked for an MSD workflow on a DGEBA/PACM network
1144
+ (2026-09-12), and the only thing to point them at was `gmx msd` directly.
1145
+ The trap for whoever adds one: `gmx msd` defaults to `-rmpbc`, which tries to
1146
+ make each molecule whole every frame, and for a periodic network that is
1147
+ impossible. It does not fail -- it prints "inconsistent shifts" and silently
1148
+ inflates the MSD, by about 2.4x at 100 ps on example 3 (0.379 against 0.154
1149
+ nm^2). The correct recipe is `trjconv -pbc nojump` and then
1150
+ `gmx msd -normpbc`. Avoid `-nopbc`, which segfaulted `gmx msd` in GROMACS
1151
+ 2025.4. `-mol` is meaningless, since the whole network is one molecule. The
1152
+ documented recipe is on the "Analyzing Trajectories of Periodic Networks"
1153
+ page.
1154
+
1155
+ Relatedly, the existing `freevolume` stage passes no `-normpbc`, so it also
1156
+ prints the warnings. For free volume they are harmless -- 0.211 +/- 0.007
1157
+ with default settings against 0.210 +/- 0.006 with `-normpbc` -- but they are
1158
+ noise a user will reasonably worry about. Adding `-normpbc` to its defaults
1159
+ would silence them; it is not done yet because `Analyze`'s option dict
1160
+ expects key/value pairs, and a bare boolean flag needs checking there.
1161
+
954
1162
  ## Example depot
955
1163
 
956
1164
  - **Example 6's postcure anneal peaks too close to *T*:sub:`g` to relax the
@@ -18,7 +18,10 @@ This kicks off the full workflow:
18
18
  2. **Initial pack.** 1000 copies of styrene are placed into a box sized
19
19
  for ``initial_density: 300 kg/m³``.
20
20
  3. **Densification.** The cascade under ``densification`` runs:
21
- minimization, 10 ps NVT, 200 ps NPT at 10 bar.
21
+ minimization, 10 ps NVT, then 200 ps NPT at 10 bar *repeated until the
22
+ density settles*. On a 24-core run that took two extra segments, so
23
+ 600 ps of NPT rather than 200, and densification as a whole took about
24
+ 5.5 minutes.
22
25
  4. **Anneal cascade.** The cascade under ``precure`` runs:
23
26
  pre-equilibration, two 300/600 K cycles, post-equilibration.
24
27
 
@@ -31,7 +31,8 @@ same as in :ref:`example 0 <liquid_styrene_run>`; the new ones are
31
31
  sized for ``initial_density: 300 kg/m³``.
32
32
 
33
33
  3. **densification.** Minimization → 10 ps NVT @ 300 K → 200 ps NPT
34
- @ 300 K, 10 bar.
34
+ @ 300 K, 10 bar, the NPT stage repeating until the density settles
35
+ (one extra segment on a 24-core run; ~4 minutes in total).
35
36
 
36
37
  4. **precure.** Pre-equilibration, two 300/600 K annealing cycles,
37
38
  post-equilibration.
@@ -88,7 +88,7 @@ With ``desired_conversion: 0.95`` and a max of 300 bonds, the target is
88
88
  default 0.5 nm search radius; as conversion approaches the target, the
89
89
  remaining reactive pairs get sparser and ``htpolynet`` has to grow the
90
90
  radius (and sometimes drag pairs in) to find anything. A typical run
91
- needs ~12–15 iterations at the default ``min_bonds_per_iteration: 10``.
91
+ needs ~10–15 iterations at the default ``min_bonds_per_iteration: 10``.
92
92
  Excerpted from a representative log:
93
93
 
94
94
  .. code-block:: text