htpolynet 2.10.3__tar.gz → 2.11.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 (368) hide show
  1. {htpolynet-2.10.3 → htpolynet-2.11.0}/CHANGELOG.md +150 -0
  2. {htpolynet-2.10.3 → htpolynet-2.11.0}/PKG-INFO +1 -1
  3. {htpolynet-2.10.3 → htpolynet-2.11.0}/ROADMAP.md +426 -0
  4. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/htpolynetpackage.rst +20 -0
  5. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/container-usage.rst +7 -1
  6. {htpolynet-2.10.3 → htpolynet-2.11.0}/pyproject.toml +1 -1
  7. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/configuration.py +2 -0
  8. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/molecule.py +142 -46
  9. htpolynet-2.11.0/src/htpolynet/core/productsplice.py +266 -0
  10. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/runtime.py +185 -1
  11. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/topocoord.py +11 -0
  12. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/topology.py +24 -0
  13. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cure/curecontroller.py +20 -3
  14. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cure/expandreactions.py +11 -1
  15. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cure/reaction.py +89 -0
  16. htpolynet-2.11.0/src/htpolynet/cure/ringcontroller.py +303 -0
  17. htpolynet-2.11.0/src/htpolynet/cure/triplesearch.py +251 -0
  18. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/gromacs.py +47 -1
  19. htpolynet-2.11.0/src/htpolynet/geometry/placement.py +100 -0
  20. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/schema/base.yaml +81 -0
  21. htpolynet-2.11.0/tests/unit/test_mdrun_gpu_options.py +87 -0
  22. htpolynet-2.11.0/tests/unit/test_multibody_reactions.py +253 -0
  23. htpolynet-2.11.0/tests/unit/test_placement_and_ringclose.py +133 -0
  24. htpolynet-2.11.0/tests/unit/test_productsplice.py +219 -0
  25. htpolynet-2.11.0/tests/unit/test_ringcontroller.py +224 -0
  26. htpolynet-2.11.0/tests/unit/test_triplesearch.py +208 -0
  27. htpolynet-2.10.3/tests/unit/test_mdrun_gpu_options.py +0 -49
  28. {htpolynet-2.10.3 → htpolynet-2.11.0}/.claude/settings.json +0 -0
  29. {htpolynet-2.10.3 → htpolynet-2.11.0}/.claude/skills/htpolynet/SKILL.md +0 -0
  30. {htpolynet-2.10.3 → htpolynet-2.11.0}/.envrc +0 -0
  31. {htpolynet-2.10.3 → htpolynet-2.11.0}/.github/workflows/conda-forge-sync.yml +0 -0
  32. {htpolynet-2.10.3 → htpolynet-2.11.0}/.github/workflows/docker.yml +0 -0
  33. {htpolynet-2.10.3 → htpolynet-2.11.0}/.github/workflows/docs.yml +0 -0
  34. {htpolynet-2.10.3 → htpolynet-2.11.0}/.github/workflows/release.yaml +0 -0
  35. {htpolynet-2.10.3 → htpolynet-2.11.0}/.github/workflows/test.yml +0 -0
  36. {htpolynet-2.10.3 → htpolynet-2.11.0}/.gitignore +0 -0
  37. {htpolynet-2.10.3 → htpolynet-2.11.0}/.readthedocs.yaml +0 -0
  38. {htpolynet-2.10.3 → htpolynet-2.11.0}/CITATION.cff +0 -0
  39. {htpolynet-2.10.3 → htpolynet-2.11.0}/CLAUDE.md +0 -0
  40. {htpolynet-2.10.3 → htpolynet-2.11.0}/LICENSE +0 -0
  41. {htpolynet-2.10.3 → htpolynet-2.11.0}/MANIFEST.in +0 -0
  42. {htpolynet-2.10.3 → htpolynet-2.11.0}/README.md +0 -0
  43. {htpolynet-2.10.3 → htpolynet-2.11.0}/docker/Dockerfile +0 -0
  44. {htpolynet-2.10.3 → htpolynet-2.11.0}/docker/compose.yml +0 -0
  45. {htpolynet-2.10.3 → htpolynet-2.11.0}/docker/docker-entrypoint.sh +0 -0
  46. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/Makefile +0 -0
  47. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/README.rst +0 -0
  48. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/make.bat +0 -0
  49. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/requirements.txt +0 -0
  50. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/_static/.gitkeep +0 -0
  51. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/_static/htpolynet-favicon.ico +0 -0
  52. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/_static/htpolynet-landing.jpg +0 -0
  53. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/_static/htpolynet-logo-dark.png +0 -0
  54. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/_static/htpolynet-logo-light.png +0 -0
  55. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/changelog.rst +0 -0
  56. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/conf.py +0 -0
  57. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
  58. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
  59. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
  60. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
  61. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
  62. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
  63. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
  64. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
  65. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
  66. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
  67. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
  68. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
  69. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
  70. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  71. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  72. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  73. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  74. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  75. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
  76. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  77. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  78. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  79. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
  80. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
  81. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
  82. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
  83. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
  84. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
  85. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
  86. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
  87. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
  88. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
  89. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
  90. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  91. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  92. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  93. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
  94. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
  95. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
  96. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
  97. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  98. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  99. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  100. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
  101. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  102. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
  103. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
  104. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
  105. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
  106. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
  107. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
  108. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
  109. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
  110. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
  111. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
  112. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
  113. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
  114. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
  115. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
  116. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
  117. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  118. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  119. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  120. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
  121. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  122. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  123. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  124. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
  125. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
  126. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
  127. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
  128. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
  129. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
  130. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
  131. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
  132. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
  133. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
  134. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
  135. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
  136. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  137. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
  138. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
  139. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
  140. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
  141. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
  142. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
  143. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
  144. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
  145. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
  146. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
  147. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
  148. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  149. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  150. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  151. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
  152. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  153. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  154. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  155. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  156. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
  157. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
  158. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
  159. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
  160. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
  161. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
  162. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
  163. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
  164. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  165. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  166. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  167. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
  168. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  169. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  170. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  171. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  172. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
  173. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
  174. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
  175. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
  176. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
  177. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
  178. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
  179. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
  180. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
  181. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  182. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  183. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  184. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  185. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  186. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  187. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  188. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +0 -0
  189. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
  190. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
  191. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
  192. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/example-tutorials/index.rst +0 -0
  193. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/index.rst +0 -0
  194. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/install.rst +0 -0
  195. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/references/index.rst +0 -0
  196. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/references/mol2-reference.pdf +0 -0
  197. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/references.bib +0 -0
  198. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/CURE.odg +0 -0
  199. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/bond_filter.odg +0 -0
  200. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/building-a-system.rst +0 -0
  201. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
  202. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  203. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/configs/configs-for-run.rst +0 -0
  204. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/configuration-files.rst +0 -0
  205. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/flow1.odg +0 -0
  206. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/flow1yaml.odg +0 -0
  207. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/hydrogenated.eps +0 -0
  208. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/hydrogenated.fig +0 -0
  209. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/index.rst +0 -0
  210. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
  211. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/periodic-networks.rst +0 -0
  212. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/STY.png +0 -0
  213. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/STYCC.png +0 -0
  214. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  215. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
  216. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  217. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  218. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  219. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  220. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  221. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/postcure-repair.rst +0 -0
  222. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/program-flow.rst +0 -0
  223. {htpolynet-2.10.3 → htpolynet-2.11.0}/docs/source/user-guide/usage.rst +0 -0
  224. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/check-conda-sync.py +0 -0
  225. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/release.sh +0 -0
  226. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/render-detail.sh +0 -0
  227. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/render-detail.tcl +0 -0
  228. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/render-snapshot.sh +0 -0
  229. {htpolynet-2.10.3 → htpolynet-2.11.0}/scripts/run_all_examples.sh +0 -0
  230. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/__init__.py +0 -0
  231. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/analysis/__init__.py +0 -0
  232. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/analysis/analyze.py +0 -0
  233. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/analysis/plot.py +0 -0
  234. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/analysis/postsim.py +0 -0
  235. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/analysis/utils.py +0 -0
  236. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cli.py +0 -0
  237. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/__init__.py +0 -0
  238. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/bondtemplate.py +0 -0
  239. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/coordinates.py +0 -0
  240. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/paramcache.py +0 -0
  241. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/core/projectfilesystem.py +0 -0
  242. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cure/__init__.py +0 -0
  243. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/cure/chain.py +0 -0
  244. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/__init__.py +0 -0
  245. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/ambertools.py +0 -0
  246. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/command.py +0 -0
  247. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/slurm.py +0 -0
  248. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/smiles_input.py +0 -0
  249. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/external/software.py +0 -0
  250. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/__init__.py +0 -0
  251. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/bondlist.py +0 -0
  252. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/lattice.py +0 -0
  253. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/linkcell.py +0 -0
  254. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/matrix4.py +0 -0
  255. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/geometry/ring.py +0 -0
  256. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/io/__init__.py +0 -0
  257. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/io/gro.py +0 -0
  258. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/io/mol2.py +0 -0
  259. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/io/pdb.py +0 -0
  260. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/repair/__init__.py +0 -0
  261. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/repair/cyanate_cap.py +0 -0
  262. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/repair/topology_surgery.py +0 -0
  263. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/README.md +0 -0
  264. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/__init__.py +0 -0
  265. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/claude/SKILL.md +0 -0
  266. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
  267. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
  268. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
  269. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
  270. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
  271. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
  272. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
  273. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/README.md +0 -0
  274. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  275. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  276. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  277. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
  278. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  279. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  280. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  281. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  282. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  283. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  284. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  285. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  286. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  287. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  288. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  289. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  290. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  291. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
  292. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  293. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  294. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  295. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  296. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  297. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  298. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  299. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  300. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  301. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
  302. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  303. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  304. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  305. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
  306. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
  307. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  308. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  309. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
  310. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/__init__.py +0 -0
  311. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/banner.py +0 -0
  312. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/checkpoint.py +0 -0
  313. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/convergence.py +0 -0
  314. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/dataframetools.py +0 -0
  315. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/inputcheck.py +0 -0
  316. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/logsetup.py +0 -0
  317. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/profiling.py +0 -0
  318. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/stringthings.py +0 -0
  319. {htpolynet-2.10.3 → htpolynet-2.11.0}/src/htpolynet/utils/vmd_viz.py +0 -0
  320. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/__init__.py +0 -0
  321. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/conftest.py +0 -0
  322. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/__init__.py +0 -0
  323. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/config1.gro +0 -0
  324. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/config1.top +0 -0
  325. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/config2.gro +0 -0
  326. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/config2.top +0 -0
  327. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/items31.edr +0 -0
  328. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/items43.edr +0 -0
  329. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/items45.edr +0 -0
  330. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/fixtures/short.mdp +0 -0
  331. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_bondtemplate.py +0 -0
  332. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_cap_placement.py +0 -0
  333. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_chain.py +0 -0
  334. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_completion_bias.py +0 -0
  335. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_conda_sync.py +0 -0
  336. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_configuration.py +0 -0
  337. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_convergence.py +0 -0
  338. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_cure_site_functionality.py +0 -0
  339. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_dataframetools.py +0 -0
  340. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_density_gate.py +0 -0
  341. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_gpu_usability.py +0 -0
  342. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
  343. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
  344. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_inputcheck.py +0 -0
  345. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_linkcell_pierce.py +0 -0
  346. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_mol2_bond_fallback.py +0 -0
  347. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_molecule_charge_report.py +0 -0
  348. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_moleculetype_name.py +0 -0
  349. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_paramcache.py +0 -0
  350. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_paramcache_ambertools.py +0 -0
  351. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_parameterize_react.py +0 -0
  352. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_plot_smoke.py +0 -0
  353. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_projectfilesystem.py +0 -0
  354. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_relax_instrumentation.py +0 -0
  355. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_repair_charge_neutrality.py +0 -0
  356. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_repair_conversion.py +0 -0
  357. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_resources.py +0 -0
  358. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_ring.py +0 -0
  359. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_ring_pierce_figs.py +0 -0
  360. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_setup_claude.py +0 -0
  361. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_sibling_templates.py +0 -0
  362. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_slurm_script.py +0 -0
  363. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_smiles_input.py +0 -0
  364. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_software_provenance.py +0 -0
  365. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_topology/test.top +0 -0
  366. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_topology.py +0 -0
  367. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_transrot_turn_scan.py +0 -0
  368. {htpolynet-2.10.3 → htpolynet-2.11.0}/tests/unit/test_user_frcmod.py +0 -0
@@ -7,6 +7,156 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.11.0] - 2026-09-22
11
+
12
+ ### Added
13
+
14
+ - **A three-body cure reaction: cyclotrimerization** (see `ROADMAP.md`). A
15
+ `reactions` entry whose bonds close a ring among three reactants, plus a
16
+ `ring_cure` configuration block, now build a network by the real cyanate-ester
17
+ chemistry -- three -O-C#N groups closing one triazine -- instead of the
18
+ pre-formed-triazine surrogate that needs postcure repair. CURE is untouched
19
+ and remains the default; a configuration without a ring-closing reaction
20
+ behaves exactly as before.
21
+
22
+ Verified end to end twice. On 90 methyl cyanates, which can only trimerize:
23
+ 19 triazines, 63% conversion, every ring six-membered with three aromatic
24
+ carbons and three aromatic nitrogens, bonds averaging 1.351 A (a triazine's
25
+ is 1.34) and planar to 0.065 A, the 33 unreacted groups keeping their C#N at
26
+ 1.153 A, and all 52 molecules neutral. Then on 100 ethylene dicyanates,
27
+ which gel: 50 triazines, 75% conversion, ring bonds averaging 1.347 A, 55
28
+ monomers reacted through both arms and 40 through one, no chemically
29
+ impossible bond, and the largest of the 8 remaining molecules holding 1068 of
30
+ 1200 atoms -- a percolating network.
31
+
32
+ Then at scale, on 150 bisphenol A dicyanates -- the real monomer, 35 atoms
33
+ rather than 12, with a rigid aromatic backbone and its two arms about 0.9 nm
34
+ apart: 61 triazines at 61% conversion, every unit six-membered with three
35
+ aromatic nitrogens and three ring carbons still carrying their ester oxygen,
36
+ ring bonds averaging 1.347 A, no bond anywhere longer than 2.5 A, 54 monomers
37
+ reacted through both arms and 75 through one, all 150 molecules neutral, and
38
+ the largest of the 30 remaining components holding 1295 of 5250 atoms.
39
+
40
+ A monomer with more than one reactive site needs two things beyond the
41
+ single-site case, both of which the difunctional build exposed:
42
+ - **Only the reacting site's share of a residue is spliced.** A dicyanate can
43
+ join two rings, and the trimer template shows one arm reacted, so splicing
44
+ the whole residue reset the other ring's arm -- 36 bonds between an aromatic
45
+ nitrogen and an unreacted cyanate carbon in the first attempt. Each atom is
46
+ assigned to whichever site is nearer through the residue's own bonds.
47
+ - **The template's atom names are translated for a residue that rings through
48
+ its other site.** That exchange moves every atom of the arm, hydrogens
49
+ included, so it is derived as an automorphism of the monomer's bond graph
50
+ rather than read off `symmetry_equivalent_atoms`, which names only the
51
+ reactive atoms. The sets are still consulted for which sites exist.
52
+
53
+ A ring-closing reaction is also exempt from symmetry expansion, which permutes
54
+ each reactive atom independently: for three dicyanates that produced 64
55
+ reactions, most of them mixing the two arms of one site, and a template for
56
+ each.
57
+ - A reaction's residue-offset arithmetic now works for any number of
58
+ reactants. It was written for exactly two, so a bond between the first and
59
+ third reactant of a three-reactant reaction resolved to the wrong residue.
60
+ - `reaction.is_ring_closing` recognizes a reaction whose bonds close a cycle
61
+ among its reactants, which a cyclotrimerization does (1-2, 2-3, 3-1) even
62
+ though its new bonds alone form no cycle -- the ring closes through bonds
63
+ each reactant already had.
64
+ - The pairwise bond search now skips such a reaction with a warning naming
65
+ it, rather than treating its bonds as three unrelated pairwise candidates
66
+ and forming them in separate iterations, which would not build a ring.
67
+ - A reaction bond can declare `sacrificial_h: false`, for an addition where
68
+ nothing is lost. Every reaction htpolynet had before is a condensation
69
+ that deletes one hydrogen from each of the bond's atoms, which stays the
70
+ default; cyclotrimerization forms three bonds and deletes no atom.
71
+ - `reaction.spanning_and_closing_bonds` separates the bonds that assemble a
72
+ product from the bond that closes its ring. A template build positions
73
+ each incoming piece as it bonds it, which a closing bond cannot do: the
74
+ residues it joins are already placed, so it is skipped there and its
75
+ geometry handled separately.
76
+ - `Runtime.do_ring_cure` runs it as a workflow stage, with restart state
77
+ beside the cure's. `do_cure` now returns early when every cure reaction
78
+ closes a ring: the pairwise search skips those, so it would otherwise
79
+ iterate to its limit forming nothing. (The `CURE` block is present even
80
+ when a configuration omits it, since the schema supplies its defaults.)
81
+ - `cure.ringcontroller` runs the loop: search, pull every chosen ring shut,
82
+ form its bonds, splice the trimer template over its three residues, settle
83
+ the charge, and count what was consumed. Conversion is counted in reactive **groups**, three per
84
+ ring, which is what this chemistry reports -- the pre-formed-triazine route
85
+ has to infer it from a bond count instead. The search widens until an
86
+ iteration yields `min_rings_per_iteration` rings, as the pairwise cure's
87
+ does for bonds. Its state round-trips to YAML for restart, carrying the
88
+ widened radius with it.
89
+ - `cure.triplesearch` finds the triangles of reactive groups one ring-closing
90
+ reaction can join. The pairwise search cannot: it asks which A atom is near
91
+ which B atom, while a cyclotrimerization needs three groups mutually close,
92
+ and two well-chosen groups can still leave the third far off. Candidates
93
+ are scored as whole triangles by their total new-bond length, both ring
94
+ orientations are tried, each group may join only one triple, and a group is
95
+ identified by residue *and* atom names -- a bisphenol dicyanate carries two,
96
+ which is what makes it a crosslinker. Two groups of one residue, or of one
97
+ molecule, are excluded by default. On a 720-molecule box (1440 groups) at
98
+ a 0.5 nm radius it finds 358 candidates in half a second and packs 148
99
+ triples from them.
100
+ - A reaction bond that consumes no hydrogen is positioned by
101
+ `Molecule.place_for_addition` rather than `transrot`, which aligns two
102
+ reactants on the hydrogens they are about to lose and so cannot place an
103
+ addition at all: in a cyclotrimerization neither the cyanate carbon nor its
104
+ nitrogen carries one. The new placement puts the incoming piece a bond
105
+ length away, in the direction and at the turn that leave the most room,
106
+ using one shared copy of that geometry in `geometry.placement`.
107
+ - `Molecule.close_ring_geometry` pulls a ring shut before its bonds exist,
108
+ by restraining every pair of the ring and stepping the restraints down to a
109
+ bond length under minimization. The merged reactants' topology is already
110
+ valid for MD, and a type-6 restraint needs no atom types, so this needs
111
+ nothing parameterized.
112
+ - `Topology.set_restraint_parameters` prescribes a restraint's length and
113
+ stiffness outright. `attenuate_bond_parameters` cannot serve here: it
114
+ reads each bond's reference values from the row it overwrites, which is
115
+ stable for a real bond, whose reference comes from its atom types, but
116
+ compounds on a restraint carrying explicit parameters -- an eight-stage
117
+ ladder ended 400 times too weak to pull anything.
118
+ - `core.productsplice.map_product_from_template` makes the residues of one
119
+ reaction event match a product template exactly -- atom types, charges, and
120
+ every bond, angle, dihedral and 1-4 pair among them, replacing the
121
+ instance's parameters where they exist and adding them where they do not.
122
+ This is what a ring closure needs and what the per-bond splice cannot do:
123
+ among the interactions a triazine closure changes are ones wholly inside a
124
+ residue (a cyanate C#N becoming a ring bond), which contain no new bond and
125
+ so are never revisited by `map_from_templates`. It takes the residue
126
+ correspondence from its caller rather than inferring it from local context,
127
+ refuses a residue map that does not explain the bonds it was given, and
128
+ refuses by default to run before those bonds exist.
129
+
130
+ ### Fixed
131
+
132
+ - **A ring cure now widens its search radius when an iteration is short of
133
+ rings, not only when it finds none.** The pairwise cure has always grown its
134
+ radius within an iteration until it has `min_bonds_per_iteration` bonds; the
135
+ ring loop instead widened only after an iteration that found nothing at all.
136
+ A floppy monomer never noticed, but a rigid one keeps trickling one or two
137
+ rings at the starting radius, so the radius never grew: 150 bisphenol A
138
+ dicyanates stopped at conversion 0.40 after eight iterations, having asked for
139
+ 0.60 and never once widened. With the same rule the pairwise cure uses --
140
+ counted in rings, and clamped against the rings still needed to reach the
141
+ target -- the same system reaches 0.61 in eight iterations. The floor is
142
+ `ring_cure: min_rings_per_iteration`, default 4.
143
+
144
+ - **A GPU build died at its first minimization when the configuration set
145
+ `ntomp`.** GROMACS refuses OpenMP threads together with a GPU unless it is
146
+ also told how many ranks to run: "Please specify the number of thread-MPI
147
+ ranks as well (option -ntmpi)." Nothing supplied one, so every such build
148
+ failed about a minute in, after parameterization had already been paid for.
149
+ htpolynet now passes `-ntmpi 1` when a configuration asks for a GPU, sets
150
+ `ntomp`, and gives no rank count of its own. A rank count in the
151
+ configuration (`ntmpi`, `nt` or `npme`) is left as it is, and so is an MPI
152
+ `mdrun`, which takes its ranks from `mpirun` or `srun` and rejects
153
+ `-ntmpi`. Reported by htpolynet-study from a 9-task GPU build where every
154
+ task failed.
155
+
156
+ - **`ntmpi` passed as a keyword argument to `grompp_and_mdrun` was dropped**,
157
+ because the passthrough list spelled it `ntpmi`. Configurations were
158
+ unaffected: `mdrun_options` is copied whole.
159
+
10
160
  ## [2.10.3] - 2026-09-17
11
161
 
12
162
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: htpolynet
3
- Version: 2.10.3
3
+ Version: 2.11.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/
@@ -199,6 +199,418 @@ Coverage as of the last measurement: **38.8%** overall.
199
199
 
200
200
  ## Cure and repair
201
201
 
202
+ - **Filtering candidate crosslinks against disallowed topologies, and what that means
203
+ for cyanate esters.** Raised by Cameron 2026-09-21, who asked the right question:
204
+ can "physically disallowable" even be defined for these systems? Partly. Three
205
+ classes, in descending order of how firm the ground is.
206
+
207
+ **What is filtered today.**
208
+ - `TopoCoord.makes_shortcircuit` rejects a candidate whose two atoms sit in
209
+ residues that are *already* bonded to each other, so one pair of residues cannot
210
+ be doubly bonded. Live for every chemistry.
211
+ - `TopoCoord.pierces_ring` rejects a candidate whose segment passes through an
212
+ existing covalent ring, and can dump a gro file of the piercing. Live, and the
213
+ one genuinely topological test in the code.
214
+ - **The cycle-length filter is inert for cyanate esters.**
215
+ `min_allowable_bondcycle_length` is read into `TC.min_bondcycle_length`, but the
216
+ only code that consults it is the C-C bondchain pass, which exists for vinyl
217
+ chain growth; `makes_bondcycle` itself is commented out in `bondtest`. For an
218
+ ether O-C bond, `chain_of` returns None and the whole check is skipped. So
219
+ example 6 and the study's bridge series have run with **no cycle filter at all**,
220
+ and the config key silently does nothing there. Worth saying out loud before
221
+ designing more filters.
222
+
223
+ **Class 1, firm: valence and connectivity.** Already handled by `z` bookkeeping
224
+ and the short-circuit test. One gap arrives with the three-body reaction above: two
225
+ -OCN groups of the *same* molecule entering the *same* triazine. Not forbidden by
226
+ valence, and Lin & Khare forbade the analogous intramolecular loop by fiat. Make it
227
+ a constraint of the triple search (one group per molecule per ring) with a config
228
+ switch, not a post-hoc rejection.
229
+
230
+ **Class 2, firm: catenation and threading.** `pierces_ring` is one-directional: it
231
+ asks whether a *new bond* pierces an *existing ring*. Cyclotrimerization creates
232
+ rings in situ, so the complementary test is needed -- does a *newly formed ring*
233
+ encircle an existing strand? Without it, trimerization can build catenanes that no
234
+ chemistry would produce and no MD will undo. This is a real, definable test and
235
+ should land with the three-body work.
236
+
237
+ **What the existing networks actually contain (htpolynet-study, 2026-09-21).**
238
+ Measured on the v5 builds, 96 cured cells, 1440 bisphenol + 960 TAZ;
239
+ `drops/htpolynet-study-cycle-sizes-20260921.md`, scripts and JSON in the study tree.
240
+ - The atom-level shortest cycle through a cure bond is **quantized at 14n, with a
241
+ floor of 28 in every cell, every conversion, every bridge.** Nothing shorter
242
+ occurs. 14 atoms is one junction-to-junction repeat (O + 4 aryl + X + 4 aryl + O,
243
+ plus C-N-C through the triazine); a chemistry with a direct biphenyl link would
244
+ give 13, so **14 is not a constant to hardcode**.
245
+ - A 28-ring is two triazines joined by two *different* bisphenols. Double-bridged
246
+ triazine pairs are 1.4% of bridges at chi = 0.99 (1540 instances). **They form
247
+ late, and kinetically they must.** Replaying the DEBUG bond table, which carries
248
+ residue numbers, dates every ring closure: over 32 c099 cells and 45,199 bridge
249
+ completions, the instantaneous closure rate per 100 bridges runs
250
+ 0.21 -> 0.83 -> 1.46 -> 1.83 -> 2.55 -> 1.98 -> 1.01 across conversion, and the
251
+ median closure sits at chi 0.819 against 0.732 for bridges generally. A second
252
+ bridge requires the triazine pair to be connected already, so the rate is first
253
+ connectivity-gated and then end-group-limited. (An earlier note here called the
254
+ rate "flat and suspicious"; that was an artifact of comparing *cumulative* ratios
255
+ at 0.90/0.95/0.99, which all sit in the plateau of a saturating curve --
256
+ htpolynet-study, retracted 2026-09-21, `bridge-series/ring_history.py`.)
257
+ - Intramolecular loops, both arms of one bisphenol into one triazine, a 14-ring:
258
+ **zero in 96 cells, zero in ~250,000 bridges.**
259
+ - **And the reason is `makes_shortcircuit`, not geometry** -- which turned up
260
+ something worth knowing. That test keys on the `molecule` gro attribute, which is
261
+ set at template build and replication and **never updated when a cure bond merges
262
+ two molecules**. So it asks only "are these two monomer instances already
263
+ directly bonded to each other?", which forbids exactly the 14-ring and nothing
264
+ else. The staleness is load-bearing: were `molecule` the current connected
265
+ component, the test would reject every cycle-closing bond and no system could gel
266
+ (ours carry a cycle rank of ~430 on ~938 junctions). Now noted in the code at
267
+ both sites that read it, so it does not get "fixed".
268
+
269
+ **Class 3, soft: strained cycles, and the threshold problem.** For cyanate esters
270
+ this class is where a filter does *harm* if switched on -- see the end-group
271
+ arithmetic below -- so what follows is a facility for other chemistries, not a
272
+ correction for this one. A candidate bond
273
+ whose two atoms are already close *through the bond graph* closes a covalent cycle.
274
+ Small ones are unphysical -- a cycle threading a few rigid aromatic units cannot
275
+ close without absurd strain -- but "small" needs a number, and inventing one is
276
+ how a filter starts rejecting chemistry that is fine. The clean generalization is
277
+ a **graph-distance filter**: reject a candidate when the shortest existing bond path
278
+ between its atoms is under N bonds, with N from config, computed by a BFS bounded at
279
+ N on `Topology.bondlist`, which is cheap and chemistry-agnostic. It subsumes the
280
+ vinyl-only cycle logic conceptually and catches the same-molecule-twice case for
281
+ free.
282
+ - **The data says this filter is insurance, not a correction.** The floor is a
283
+ 28-membered macrocycle -- large and unstrained -- and the one strained candidate,
284
+ the 14-ring, is already excluded. Because the spectrum is quantized, N has few
285
+ distinct settings in this chemistry: 15 <= N <= 28 is a no-op, N = 29 removes the
286
+ 28-rings, N = 43 removes 28s and 42s.
287
+ - **Count crosslinker repeats, not atoms** (the study's ask, and it is right).
288
+ "Reject a bond closing a cycle spanning fewer than k junction-to-junction
289
+ repeats" reads off the junction graph, is chemistry-independent, and avoids a
290
+ per-chemistry magic number.
291
+ - **Off by default is the CORRECT default for cyanate esters, not a cautious one --
292
+ and the docs and the code comment must say why.** htpolynet-study, 2026-09-21,
293
+ from the library: Fang & Shimp's end-group arithmetic caps acyclic dendritic
294
+ growth at **75%** cyanate conversion, a mild ring-chain model at **90%**, and only
295
+ severe macrocyclization reaches **98%**. Real cure reaches 98-99%, and Guenthner
296
+ 2014 treats the point as settled. **A 98% polycyanurate network cannot be
297
+ macrocycle-free.** Filtering short cycles out of this chemistry would therefore
298
+ remove the very structures that let it cure at all.
299
+ - **The convention we would be importing comes from a different chemistry.** Khare
300
+ 2018 and Lin 2009 justify prohibiting short cycles for **epoxy-amine**, where they
301
+ are negligible. That justification inverts for cyanate esters. Put this in a
302
+ comment where the filter is defined, because the filter will otherwise look
303
+ under-used and someone will helpfully turn it on.
304
+ - **If anything, we make too few.** Two independent measures: cycle rank per
305
+ monomer **0.303 against Fang's 0.485**, and a gel-point delay of **+6.3% against
306
+ Lin's +21%** cyclization term. So the interesting question for cyanate esters is
307
+ not how to suppress cycles but why htpolynet produces fewer than the chemistry
308
+ demands -- plausibly the 0.5 nm search radius and junctions seeded at t=0. That
309
+ is a separate investigation, and the three-body reaction changes its terms, since
310
+ junctions would then emerge where ends meet.
311
+ - The 28-rings are near-unstrained in GAFF (span -0.07 A, C-O-C angle -0.46 deg
312
+ against non-ring bridges), but that only says the force field tolerates them.
313
+ Their absolute frequency is still set by our search radius and seeded junctions,
314
+ so **1.4% must never be quoted as a physical cyclization rate**; the comparison
315
+ against Fang above is the meaningful one.
316
+ - **Do not validate the filter on Tg in this system -- it is underpowered, and
317
+ that is bounded, not guessed.** Between-bridge spread in ring density is 0.67
318
+ percentage points of bridges, and dTg/dconversion averages 5.6 K per percentage
319
+ point of bonds, so even if every ring bridge were completely elastically dead the
320
+ differential Tg across bridges is <= 3.8 K and the absolute effect <= 8.0 K --
321
+ against a replicate standard deviation of 12.5-25.0 K at chi 0.99 with n = 4. A
322
+ null result would mean nothing.
323
+ - **Validate it structurally instead.** Correctness on synthetic graphs (it rejects
324
+ what it should, and nothing else) plus structural observables that respond
325
+ directly and cheaply -- cycle rank, the count of elastically effective strands,
326
+ the fragment distribution -- rather than a thermal property the system cannot
327
+ resolve. If a thermal effect is ever wanted, it needs a system engineered for a
328
+ high ring density, not this one.
329
+ - **Re-measure for cyclotrimerization.** These statistics come from the A2+B3
330
+ route, where junctions are seeded at t=0 by random insertion rather than emerging
331
+ where three ends meet, and the cycle spectrum inherits that. They are a
332
+ measurement of what htpolynet builds this way, not of polycyanurate.
333
+ - **Under the three-body reaction the same-molecule case aborts rather than
334
+ declines.** `makes_shortcircuit` opens with `assert i_resNum != j_resNum`
335
+ (topocoord.py:1299), and two cyanate arms of one dicyanate are the *same*
336
+ residue, so routing that pair through `bondtest` raises instead of rejecting.
337
+ The triple search must exclude it **before** the pairwise test, not rely on it.
338
+ - **And the right criterion is a distance, not a same-residue veto** (study,
339
+ section 5). Two bridge positions on one triazine sit at O...O = 4.60 +/- 0.10 A
340
+ (n = 2814). Bisphenol intramolecular O...O over ~11,000 conformers of all eight
341
+ bridges: means 9.31-9.80 A, closest approach anywhere 5.93 A (a sulfone) -- still
342
+ 1.3 A short, so the 14-ring is geometrically inaccessible to these monomers and a
343
+ blanket veto would be doing no work. A shorter-span diol *could* reach 4.6 A, and
344
+ there the exclusion matters. So gate on whether the two arms' oxygens can span
345
+ the junction's bridge separation, which is chemistry-independent and does real
346
+ work in the case where the loop is actually possible.
347
+
348
+ **Where the filters have to live.** Not only in the pairwise search. The
349
+ single-step annealer chooses a whole connectivity at once, so these become
350
+ constraints on its move set (reject the move, or price it in the cost), and the
351
+ three-body search needs them as constraints on triple selection. A filter
352
+ expressed only as a post-hoc reject in `bondtest` will not transfer to either.
353
+ Factor them as predicates over (candidate, current topology) that all three callers
354
+ share.
355
+
356
+ **Reporting.** `bondtest` outcomes are already counted per `BTRC` code and logged;
357
+ extend that enum rather than inventing a parallel mechanism, and log the
358
+ per-reason histogram at each iteration. A filter that silently removes half the
359
+ candidates is worse than no filter.
360
+
361
+ - **A three-body cure reaction, for the real cyanate-ester chemistry.** Asked for by
362
+ Cameron 2026-09-21. Cyanate esters cure by *cyclotrimerization*: three -O-C#N
363
+ groups combine into one 1,3,5-triazine ring, an addition with no atom lost.
364
+ htpolynet cannot express that today -- a reaction forms one bond between two
365
+ reactants -- so example 6 and the study's whole bridge series use a surrogate: a
366
+ pre-formed TAZ triazine monomer plus aryl-ether bonds (A2 + B3), with
367
+ `postcure_repair: triazine_to_cyanate_cap` dismantling the rings that never
368
+ completed back into -OCN caps.
369
+
370
+ **Why it is worth doing.** The surrogate is wrong in ways that cost real work:
371
+ - Triazine rings exist before cure, so crosslink junctions are present at zero
372
+ conversion, and the gel point of the model is not the gel point of the chemistry.
373
+ - Incomplete rings are an artifact with no chemical counterpart, and the repair
374
+ that cleans them up is where the +/-0.24 e charge bug lived (fixed in 2.9.0).
375
+ With real trimerization an unreacted group simply stays -OCN, correct by
376
+ construction, and repair is not needed at all for new builds.
377
+ - Conversion becomes directly what the literature reports. Today a bond conversion
378
+ has to be mapped to OCN conversion (`chi_OCN ~ chi_bond^3`, exactly zero below f
379
+ iterations -- see the memory note); with trimerization, one reaction event
380
+ consumes three OCN groups and `chi_OCN` is measured, not inferred.
381
+
382
+ **What already generalizes.** `_yield_bonds_as_df` builds its bonds through a
383
+ per-reactant `resid_mapper`, so template *building* is not limited to two
384
+ reactants; `Molecule.generate` merges however many reactants it is given; a bond
385
+ record is a pair of atoms, which stays true for a ring of three bonds.
386
+
387
+ **The hard part, and the central new code.** Per-bond template splicing cannot
388
+ form a ring. `map_from_templates` matches each new bond by its local context, but
389
+ in the trimer template all three ring bonds exist, while the instance, partway
390
+ through the batch, has only some of them -- so the template's bystanders cannot
391
+ match the instance's, in either direction. A ring needs a **product-wide splice**:
392
+ map every atom of the three participating residues from the trimer template at
393
+ once -- types, charges, and all angles, dihedrals and 1-4 pairs involving the new
394
+ ring -- rather than three independent per-bond splices. Treat that as a new
395
+ function beside `map_from_templates`, not a modification of it; CURE's pairwise
396
+ path must keep working unchanged.
397
+
398
+ **Plan.**
399
+ 1. *Reaction model.* Let a cure reaction declare three reactants and three bonds.
400
+ Generalize `prepare_new_bonds`, whose residue-offset arithmetic is written for
401
+ exactly two reactants, and the `len(R.reactants) == 2` guards. Symmetry
402
+ expansion needs care but is bounded: three copies of a dicyanate with two
403
+ equivalent sites give four distinct site combinations, not eight.
404
+ 2. *The trimer template.* One product per site combination, about 120 atoms for a
405
+ real dicyanate: a one-time AM1-BCC cost of tens of minutes, then cached. Ring
406
+ closure is the question. Preferred: build it as today by merging and placing the
407
+ three pieces, then close the third bond under a type-6 restraint with the
408
+ existing attenuation ladder before parameterizing -- the drag machinery already
409
+ does exactly this. Fallback: declare the trimer from SMILES as a
410
+ `count: 0` constituent, which sidesteps the geometry but needs a way to name
411
+ residues inside one generated molecule, which htpolynet has no syntax for.
412
+ 3. *Triple search.* Enumerate candidate triples from the linkcell -- pairs within
413
+ the radius, then triangles among them -- score by the sum of the three
414
+ distances, and choose a disjoint set. Greedy is the simple version; the
415
+ set-packing problem is close enough to the single-step annealer above that the
416
+ two should share code if both get built. Forbid two groups of the same molecule
417
+ in one ring, as the single-step entry forbids intramolecular loops.
418
+ 4. *Ring closure in the system.* Three sites have to converge, which is strictly
419
+ harder than bringing two together. Restrain all three pairs, walk them in with
420
+ the drag ladder, then form the ring in one batch and relax.
421
+ 5. *Accounting and checks.* Conversion counted in OCN groups consumed, three per
422
+ event. `check_iterations_vs_functionality` assumes a residue carries its own
423
+ crosslink sites; junctions now form in situ from three molecules, so its
424
+ functionality model needs rework rather than a patch. The per-molecule charge
425
+ check applies unchanged and is worth watching, since a ring closure changes
426
+ types and charges on three residues at once.
427
+ 6. *Docs, example, validation.* A new shipped example, or an ex6 variant, built
428
+ both ways: surrogate versus true trimerization at matched conversion, comparing
429
+ density, Tg, and the fragment and junction statistics, against the study's BADCy
430
+ results. Builds belong to htpolynet-sweep.
431
+
432
+ **Risks.** Ring closure failing in a dense box is the likely one, and the
433
+ three-way convergence has no precedent in the code. Beyond that: template cost if
434
+ a system has several distinct cyanate monomers (one trimer template per
435
+ combination), and the fact that changing conversion semantics breaks comparability
436
+ with every existing cyanate build, which is a documentation problem as much as a
437
+ code one. Out of scope: the dimer and oxazoline intermediates real cyanate cure
438
+ passes through.
439
+
440
+ - **Single-step crosslinking (the Khare method), as an alternative to CURE, not a
441
+ replacement.** Agreed with Cameron 2026-09-21. All bonds are chosen at once by
442
+ combinatorial optimization on one static snapshot, before any bond exists, so
443
+ conversion is 100% by construction; the network is then relaxed into place by one
444
+ restraint-strengthening ladder applied to every bond simultaneously. CURE stays
445
+ exactly as it is and remains the default.
446
+
447
+ **Sources.** literature's spec, with every parameter attributed to the paper it
448
+ was read from, is
449
+ `~/.local/state/fleet/drops/literature-khare-crosslink-algorithm-20260921.md`.
450
+ The load-bearing ones: `Khare1993Generation` (origin; the open-TSP framing),
451
+ `Lin2009Molecular` (the only complete annealing parameter set, and the viability
452
+ gate), `Khare2012Directed` (the restraint ladder with all k and b0),
453
+ `Jang2015Comparison` (Cameron's own; the acceptance formula, and the only
454
+ head-to-head against multi-step).
455
+
456
+ **The method, as specified.**
457
+ - *Stage 1, connectivity by simulated annealing.* Cost is the total bond length
458
+ over all chosen pairs; the "temperature" is a **length**, starting at 2.5 A;
459
+ accept if the cost drops, else with `exp(-dL/L_C)`; multiply L_C by 0.95 whenever
460
+ attempted moves reach 100x or accepted moves 10x the number of reactive pairs.
461
+ The move changes only two bonds, so a trial costs O(1) -- that is what makes it
462
+ cheap (under 15 min CPU in Lin 2009). Intramolecular loops are forbidden.
463
+ - *The viability gate, and its loop.* Annealing returns a sequence, not short
464
+ bonds: the target C-N bond is 1.364 A, van der Waals approach about 3.4 A, and
465
+ most chosen pairs start much further apart. So before any bond is created, two
466
+ 50 ps NVT runs at 300 K under harmonic distance restraints at 8 A then 3 A, then
467
+ a re-scan requiring every pair under 4 A, and **on failure, re-anneal**. Lin
468
+ 2009 needed up to three passes for their nanocomposite. This loop is the
469
+ difference between a method that works and one that explodes.
470
+ - *Stage 2, directed diffusion.* Ten stages of 20 ps NVT at 703 K with
471
+ `E = k(b-b0)^2`, k in kcal/mol/A^2 and b0 in A: (1,10) (2,9) (4,8) (8,7) (16,6)
472
+ (32,5) (64,4) (128,3) (256,2) (332.7,1.458). k doubles each stage; the last is
473
+ the GAFF C-N bond itself. Then the topology and charges are updated, sacrificial
474
+ H's deleted, and MD run for 4 ns at more than 150 K above Tg.
475
+
476
+ **Decisions taken (Cameron, 2026-09-21).**
477
+ 1. **Objective:** sum of lengths by default, as the better-documented choice, with
478
+ sum of squares available as a config option. `Lin2009Molecular` and
479
+ `Jang2015Comparison` use lengths, `Khare2021Atomistic` uses squares, and no
480
+ paper reconciles the two.
481
+ 2. **Encoding:** a capacitated matching with a partner-swap move, rather than a
482
+ literal TSP path. A path whose consecutive pairs are all bonds gives every
483
+ interior site two bonds -- right for a linear chain, wrong for an epoxy carbon
484
+ that forms one. htpolynet already knows each site's functionality from `z`, so
485
+ the matching formulation handles arbitrary functionality.
486
+
487
+ **This is our design decision, not a reading of Khare.** Lin & Khare 2009
488
+ (journal pp. 4320-4321) name the problem and never state the answer: they
489
+ extended the polystyrene approach "to incorporate the modifications required to
490
+ account for the complexities (e.g., **the number of connections**) of the
491
+ unreacted epoxy monomer, cross-linker, and POSS molecules" -- and what those
492
+ modifications were appears nowhere. Their prose points both ways ("sequence of
493
+ bonds between randomly picked reacting site pairs" reads as a matching, "a path
494
+ ... that connects all of the potential reacting sites" as a Hamiltonian path),
495
+ but the move settles it: "only the bonds at the two end points of the selected
496
+ path segment get altered" is 2-opt segment reversal on a path, which on a
497
+ matching would change every pair in the segment. In Khare 1993 there was no
498
+ tension, because polystyrene is linear and an interior monomer really is
499
+ bivalent. The efficiency argument survives the change: swapping the partners of
500
+ two sites also alters exactly two bonds, so the O(1) delta that makes the
501
+ annealing schedule affordable is kept. Credit Khare for the method and say
502
+ plainly that the network adaptation is ours.
503
+ 3. **Ladder:** configurable, with the published schedules shipped as named presets.
504
+ **The 2018 SI has since landed** (literature, 2026-09-21) and the 12-stage
505
+ schedule is a different *shape*, not a longer version of the 10-stage one -- so
506
+ they are two presets, and neither may be derived from the other. Which one
507
+ should be the default is now **an open question for Cameron**: the 10-stage 2012
508
+ table was chosen when it was the only complete one, but the 12-stage schedule is
509
+ the one used in the papers that carry the validation (`Khare2018Quantitative`,
510
+ `Khare2021Atomistic`) and the only one with its full run conditions published.
511
+
512
+ *2012, `Khare2012Directed`, ten 20 ps NVT stages at 703 K:* k doubles each stage
513
+ while b0 walks down with it -- (1,10) (2,9) (4,8) (8,7) (16,6) (32,5) (64,4)
514
+ (128,3) (256,2) (332.7,1.458).
515
+
516
+ *2018 SI Table S1, twelve stages at 700 K, 10.13 MPa, 37.5 ps each:* two phases
517
+ rather than one ramp. Stages 1-5 pull b0 in from 15 A to 3 A at almost constant,
518
+ very weak k; stages 6-11 hold b0 at 1.5 A and ramp k over three decades; stage 12
519
+ switches to the real GAFF bond.
520
+
521
+ stage 1 2 3 4 5 6 7 8 9 10 11 12
522
+ k 0.0625 0.125 0.25 0.25 0.25 0.25 0.5 1 5 25 125 333.27
523
+ b0 15 12 9 6 3 1.5 1.5 1.5 1.5 1.5 1.5 1.458
524
+
525
+ Final k is 333.27 in the SI and 332.7 in the 2012 figure for the same bond; one
526
+ is a transposition or a force-field version difference. Do not read their near
527
+ agreement as confirmation of either.
528
+ 4. **Naming:** the config block is `single_step:`, not a person's name; the docs
529
+ credit Khare and cite the papers.
530
+
531
+ **The detail that is in no paper, and would otherwise have been found by failure.**
532
+ The 2018 SI states that during directed diffusion the **pairwise nonbonded
533
+ interaction between each connecting pair is switched off**: "Since Van der Waals
534
+ forces would ordinarily limit the distance between the terminal carbon atom of Epon
535
+ 1001F and the nitrogen atom of 4,4'-DDS to no less than 3.3 A, pairwise interactions
536
+ between these connecting atoms are excluded." Without that, b0 = 1.5 A is simply
537
+ unreachable and the ladder stalls against a wall it cannot cross. In GROMACS terms
538
+ this is an `[ exclusions ]` entry per candidate pair, added for the duration of the
539
+ ladder and removed when the real bond forms. **This applies to CURE's drag stage
540
+ too**, which pulls pairs together under type-6 restraints with vdW fully on -- which
541
+ is very likely what `CURE.drag.limit` exists to work around. Worth trying there
542
+ once the mechanism exists.
543
+
544
+ **Two things the SI settles, one of which matches htpolynet already.**
545
+ - *Objective:* sum of the **squares** -- "minimizing the sum of the squares of the
546
+ individual distances of each of the connections", average connection length going
547
+ from ~70 A to ~10 A. So squares is the Khare line and sum-of-lengths is Lin 2009
548
+ / Jang 2015. Our default stays lengths (decision 1), but it is now a real fork
549
+ between two published choices rather than an unresolved ambiguity, and the config
550
+ option must be documented as such.
551
+ - *Loop prevention:* "allowing only a single connection between a given pair of Epon
552
+ 1001F and 4,4'-DDS molecules". That is **exactly what htpolynet's
553
+ `makes_shortcircuit` already enforces**, via the deliberately stale `molecule`
554
+ attribute -- see the filtering entry above. Nothing to build.
555
+
556
+ **Their topology transformation, for contrast with ours.** Delete one H from each
557
+ terminal epoxy carbon and both from each amine N; **recompute partial charges near
558
+ the new bonds with AM1-BCC**; fix angles, dihedrals and impropers for GAFF
559
+ consistency; then relax 10 ns at 820 K and 5 MPa. htpolynet does this differently
560
+ and, arguably, better: charges and types come from a pre-parameterized product
561
+ template rather than an in-situ recomputation, which is reproducible and cached.
562
+ Worth saying in the docs that this is a deliberate difference from the published
563
+ method, not an oversight.
564
+
565
+ **An acceptance test to lift directly.** Figure S4 of the 2018 SI shows the epoxy
566
+ monomer end-to-end distance distribution **essentially unchanged before and after
567
+ crosslinking** -- their own check that the restraint ladder does not unphysically
568
+ stretch molecules. It is cheap, it tests the thing most likely to go wrong, and it
569
+ can be computed for CURE builds too as a baseline. Make it part of the acceptance
570
+ criteria alongside the Jang comparison.
571
+
572
+ **What it reuses.** Templates, box construction, densification and precure
573
+ unchanged; reactive-site enumeration from the same `reactions:` declarations that
574
+ CURE uses, minus the radius test, so bonds get the same template parameters;
575
+ type-6 restraints between not-yet-bonded pairs (`TopoCoord.add_restraints`), which
576
+ is the same mechanism as CURE's drag; batch bond formation through
577
+ `update_topology_and_coordinates`, which already forms hundreds of bonds per CURE
578
+ iteration; and the whole postcure path. The second-shell templates added in 2.9.0
579
+ matter here: at 100% conversion every multi-site residue ends fully substituted,
580
+ which is exactly the context they cover.
581
+
582
+ **What it needs that does not exist.**
583
+ - `src/htpolynet/singlestep/anneal.py`: cost, move set, acceptance, schedule, with
584
+ no MD in it, so it can be tested on a lattice with a known optimum.
585
+ - A controller mirroring `CureController`: the viability-gate loop, the restraint
586
+ ladder, its own restart state beside `cure_state.yaml`.
587
+ - Restraint parameters set explicitly per stage. `attenuate_bond_parameters`
588
+ interpolates from each bond's initial distance toward equilibrium; this method
589
+ prescribes (k, b0) per stage for every bond alike.
590
+ - A `single_step:` schema section, and a `do_crosslink` dispatch in the workflow
591
+ that runs either this or CURE. `do_cure` is not touched.
592
+ - One fix: `check_iterations_vs_functionality` warns when iterations < site count,
593
+ which is meaningless at 100% conversion in a single step. Skip it there.
594
+
595
+ **Validation, and the result to design against.** `Jang2015Comparison` built
596
+ chemically and stoichiometrically identical systems both ways: thermal and
597
+ mechanical properties and the N-to-N contour length distribution were insensitive
598
+ to the choice, but the fragment molecular-weight distribution after cutting each
599
+ crosslinker was **not** -- single-step gave fewer, larger fragments. The two
600
+ methods build qualitatively different networks that agree on the properties usually
601
+ reported. So the acceptance test is example 3 (DGEBA/PACM) built both ways,
602
+ comparing density, thermal and mechanical properties, N-to-N contour length, and
603
+ that fragment distribution.
604
+
605
+ **But do not treat the fragment result as a target to hit.** Because the papers
606
+ never state their network adaptation (see decision 2), that difference belongs to
607
+ whatever connectivity rule their implementation used, not to "single-step" as a
608
+ class. A capacitated matching may not reproduce it, and would not be wrong for
609
+ failing to. Read it as the reason to *measure* the fragment distribution both ways
610
+ rather than assume the networks are interchangeable; agreement on density, thermal
611
+ and mechanical properties is the part worth requiring. Builds belong to htpolynet-sweep. The per-molecule charge check applies
612
+ unchanged and is worth watching: this forms every bond in one batch.
613
+
202
614
  - **Chain-growth cure leaves whole chains charged.** The v2.10.0 sweep's new
203
615
  molecule-charge check found example 1's polystyrene warning: 7 of 49 chains
204
616
  over 0.01 e, the largest -0.040 e on the longest (1410-atom) chain, with the
@@ -1324,3 +1736,17 @@ Coverage as of the last measurement: **38.8%** overall.
1324
1736
  thioether, sulfone, dicyclopentadiene. A homologous series would
1325
1737
  exercise the repair stage across chemistries and give the tutorials a
1326
1738
  structure-property story.
1739
+
1740
+
1741
+ - **A ring-closing ladder stops around 0.22 nm, not at its 0.15 nm target.**
1742
+ The closure restraints pull three cyanate groups together before any ring bond
1743
+ exists, and they consistently stall at ~0.225 nm regardless of how far apart
1744
+ they started -- in the isolated trimer template too, so it is not crowding by
1745
+ the surrounding system. The cause is that the groups still carry their
1746
+ sp-hybridized C#N parameters while being pulled, and a linear triple bond
1747
+ resists closing the angle a triazine needs; no force constant fixes that. It
1748
+ is benign today: the bonds are formed at that length, the template splice
1749
+ replaces the types, and the relax step brings them to 1.35 A, which every
1750
+ build has confirmed. The warning threshold (twice the target) has never
1751
+ fired. If it ever does, the fix is to attenuate the C#N bonded parameters
1752
+ along the closure ladder rather than to pull harder.
@@ -60,6 +60,11 @@ htpolynet.core
60
60
  :undoc-members:
61
61
  :show-inheritance:
62
62
 
63
+ .. automodule:: htpolynet.core.productsplice
64
+ :members:
65
+ :undoc-members:
66
+ :show-inheritance:
67
+
63
68
  .. automodule:: htpolynet.core.projectfilesystem
64
69
  :members:
65
70
  :undoc-members:
@@ -121,6 +126,16 @@ htpolynet.cure
121
126
  :undoc-members:
122
127
  :show-inheritance:
123
128
 
129
+ .. automodule:: htpolynet.cure.ringcontroller
130
+ :members:
131
+ :undoc-members:
132
+ :show-inheritance:
133
+
134
+ .. automodule:: htpolynet.cure.triplesearch
135
+ :members:
136
+ :undoc-members:
137
+ :show-inheritance:
138
+
124
139
  htpolynet.external
125
140
  ------------------
126
141
 
@@ -177,6 +192,11 @@ htpolynet.geometry
177
192
  :undoc-members:
178
193
  :show-inheritance:
179
194
 
195
+ .. automodule:: htpolynet.geometry.placement
196
+ :members:
197
+ :undoc-members:
198
+ :show-inheritance:
199
+
180
200
  .. automodule:: htpolynet.geometry.ring
181
201
  :members:
182
202
  :undoc-members: