htpolynet 2.8.0__tar.gz → 2.9.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 (355) hide show
  1. {htpolynet-2.8.0 → htpolynet-2.9.0}/CHANGELOG.md +118 -0
  2. {htpolynet-2.8.0 → htpolynet-2.9.0}/PKG-INFO +1 -1
  3. {htpolynet-2.8.0 → htpolynet-2.9.0}/ROADMAP.md +44 -0
  4. {htpolynet-2.8.0 → htpolynet-2.9.0}/docker/Dockerfile +8 -1
  5. htpolynet-2.9.0/docs/source/_static/htpolynet-favicon.ico +0 -0
  6. htpolynet-2.9.0/docs/source/_static/htpolynet-landing.jpg +0 -0
  7. htpolynet-2.9.0/docs/source/_static/htpolynet-logo-dark.png +0 -0
  8. htpolynet-2.9.0/docs/source/_static/htpolynet-logo-light.png +0 -0
  9. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/conf.py +13 -0
  10. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +15 -0
  11. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/index.rst +5 -0
  12. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/install.rst +33 -6
  13. {htpolynet-2.8.0 → htpolynet-2.9.0}/pyproject.toml +1 -1
  14. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/bondtemplate.py +28 -6
  15. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/molecule.py +1 -1
  16. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/runtime.py +47 -2
  17. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/topocoord.py +71 -5
  18. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/topology.py +18 -0
  19. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cure/curecontroller.py +65 -7
  20. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cure/expandreactions.py +115 -1
  21. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/repair/cyanate_cap.py +19 -22
  22. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/repair/topology_surgery.py +73 -7
  23. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +4 -1
  24. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_completion_bias.py +33 -0
  25. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_conda_sync.py +10 -0
  26. htpolynet-2.9.0/tests/unit/test_cure_site_functionality.py +154 -0
  27. htpolynet-2.9.0/tests/unit/test_mol2_bond_fallback.py +58 -0
  28. htpolynet-2.9.0/tests/unit/test_molecule_charge_report.py +68 -0
  29. htpolynet-2.9.0/tests/unit/test_repair_charge_neutrality.py +87 -0
  30. htpolynet-2.9.0/tests/unit/test_sibling_templates.py +181 -0
  31. {htpolynet-2.8.0 → htpolynet-2.9.0}/.claude/settings.json +0 -0
  32. {htpolynet-2.8.0 → htpolynet-2.9.0}/.claude/skills/htpolynet/SKILL.md +0 -0
  33. {htpolynet-2.8.0 → htpolynet-2.9.0}/.envrc +0 -0
  34. {htpolynet-2.8.0 → htpolynet-2.9.0}/.github/workflows/conda-forge-sync.yml +0 -0
  35. {htpolynet-2.8.0 → htpolynet-2.9.0}/.github/workflows/docker.yml +0 -0
  36. {htpolynet-2.8.0 → htpolynet-2.9.0}/.github/workflows/docs.yml +0 -0
  37. {htpolynet-2.8.0 → htpolynet-2.9.0}/.github/workflows/release.yaml +0 -0
  38. {htpolynet-2.8.0 → htpolynet-2.9.0}/.github/workflows/test.yml +0 -0
  39. {htpolynet-2.8.0 → htpolynet-2.9.0}/.gitignore +0 -0
  40. {htpolynet-2.8.0 → htpolynet-2.9.0}/.readthedocs.yaml +0 -0
  41. {htpolynet-2.8.0 → htpolynet-2.9.0}/CITATION.cff +0 -0
  42. {htpolynet-2.8.0 → htpolynet-2.9.0}/CLAUDE.md +0 -0
  43. {htpolynet-2.8.0 → htpolynet-2.9.0}/LICENSE +0 -0
  44. {htpolynet-2.8.0 → htpolynet-2.9.0}/MANIFEST.in +0 -0
  45. {htpolynet-2.8.0 → htpolynet-2.9.0}/README.md +0 -0
  46. {htpolynet-2.8.0 → htpolynet-2.9.0}/docker/compose.yml +0 -0
  47. {htpolynet-2.8.0 → htpolynet-2.9.0}/docker/docker-entrypoint.sh +0 -0
  48. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/Makefile +0 -0
  49. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/README.rst +0 -0
  50. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/make.bat +0 -0
  51. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/requirements.txt +0 -0
  52. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/_static/.gitkeep +0 -0
  53. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/changelog.rst +0 -0
  54. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
  55. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
  56. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
  57. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
  58. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
  59. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
  60. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
  61. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
  62. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
  63. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
  64. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
  65. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
  66. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
  67. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
  68. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
  69. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
  70. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
  71. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
  72. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
  73. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
  74. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
  75. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
  76. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
  77. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
  78. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
  79. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
  80. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
  81. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
  82. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
  83. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
  84. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
  85. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
  86. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
  87. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
  88. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
  89. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
  90. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
  91. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
  92. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
  93. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
  94. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
  95. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
  96. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
  97. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
  98. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
  99. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
  100. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
  101. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
  102. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
  103. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
  104. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
  105. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
  106. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
  107. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
  108. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
  109. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
  110. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
  111. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
  112. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
  113. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
  114. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
  115. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
  116. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
  117. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
  118. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
  119. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
  120. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
  121. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
  122. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
  123. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
  124. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
  125. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
  126. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
  127. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
  128. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
  129. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
  130. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
  131. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
  132. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
  133. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
  134. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
  135. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
  136. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
  137. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
  138. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
  139. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
  140. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
  141. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
  142. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
  143. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
  144. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
  145. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
  146. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
  147. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
  148. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
  149. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
  150. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
  151. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
  152. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
  153. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
  154. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
  155. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
  156. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
  157. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
  158. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
  159. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
  160. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
  161. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
  162. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
  163. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
  164. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
  165. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
  166. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
  167. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
  168. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
  169. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
  170. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
  171. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
  172. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
  173. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
  174. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
  175. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
  176. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
  177. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
  178. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
  179. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
  180. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
  181. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
  182. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
  183. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
  184. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
  185. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +0 -0
  186. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
  187. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
  188. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/example-tutorials/index.rst +0 -0
  189. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/htpolynetpackage.rst +0 -0
  190. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/references/index.rst +0 -0
  191. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/references/mol2-reference.pdf +0 -0
  192. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/references.bib +0 -0
  193. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/CURE.odg +0 -0
  194. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/bond_filter.odg +0 -0
  195. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/building-a-system.rst +0 -0
  196. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
  197. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
  198. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/configs/configs-for-run.rst +0 -0
  199. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/configuration-files.rst +0 -0
  200. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/container-usage.rst +0 -0
  201. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/flow1.odg +0 -0
  202. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/flow1yaml.odg +0 -0
  203. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/hydrogenated.eps +0 -0
  204. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/hydrogenated.fig +0 -0
  205. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/index.rst +0 -0
  206. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
  207. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/periodic-networks.rst +0 -0
  208. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/STY.png +0 -0
  209. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/STYCC.png +0 -0
  210. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
  211. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
  212. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
  213. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
  214. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
  215. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
  216. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
  217. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/postcure-repair.rst +0 -0
  218. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/program-flow.rst +0 -0
  219. {htpolynet-2.8.0 → htpolynet-2.9.0}/docs/source/user-guide/usage.rst +0 -0
  220. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/check-conda-sync.py +0 -0
  221. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/release.sh +0 -0
  222. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/render-detail.sh +0 -0
  223. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/render-detail.tcl +0 -0
  224. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/render-snapshot.sh +0 -0
  225. {htpolynet-2.8.0 → htpolynet-2.9.0}/scripts/run_all_examples.sh +0 -0
  226. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/__init__.py +0 -0
  227. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/analysis/__init__.py +0 -0
  228. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/analysis/analyze.py +0 -0
  229. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/analysis/plot.py +0 -0
  230. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/analysis/postsim.py +0 -0
  231. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/analysis/utils.py +0 -0
  232. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cli.py +0 -0
  233. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/__init__.py +0 -0
  234. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/configuration.py +0 -0
  235. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/coordinates.py +0 -0
  236. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/paramcache.py +0 -0
  237. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/core/projectfilesystem.py +0 -0
  238. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cure/__init__.py +0 -0
  239. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cure/chain.py +0 -0
  240. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/cure/reaction.py +0 -0
  241. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/__init__.py +0 -0
  242. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/ambertools.py +0 -0
  243. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/command.py +0 -0
  244. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/gromacs.py +0 -0
  245. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/slurm.py +0 -0
  246. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/smiles_input.py +0 -0
  247. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/external/software.py +0 -0
  248. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/__init__.py +0 -0
  249. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/bondlist.py +0 -0
  250. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/lattice.py +0 -0
  251. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/linkcell.py +0 -0
  252. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/matrix4.py +0 -0
  253. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/geometry/ring.py +0 -0
  254. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/io/__init__.py +0 -0
  255. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/io/gro.py +0 -0
  256. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/io/mol2.py +0 -0
  257. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/io/pdb.py +0 -0
  258. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/repair/__init__.py +0 -0
  259. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/README.md +0 -0
  260. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/__init__.py +0 -0
  261. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/claude/SKILL.md +0 -0
  262. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
  263. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
  264. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
  265. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
  266. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
  267. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
  268. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/README.md +0 -0
  269. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
  270. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
  271. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
  272. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
  273. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
  274. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
  275. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
  276. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
  277. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
  278. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
  279. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
  280. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
  281. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
  282. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
  283. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
  284. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
  285. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
  286. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
  287. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
  288. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
  289. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
  290. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
  291. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
  292. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
  293. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
  294. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
  295. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
  296. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
  297. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
  298. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
  299. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
  300. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
  301. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
  302. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
  303. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
  304. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
  305. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/schema/base.yaml +0 -0
  306. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/__init__.py +0 -0
  307. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/banner.py +0 -0
  308. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/checkpoint.py +0 -0
  309. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/convergence.py +0 -0
  310. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/dataframetools.py +0 -0
  311. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/inputcheck.py +0 -0
  312. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/logsetup.py +0 -0
  313. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/profiling.py +0 -0
  314. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/stringthings.py +0 -0
  315. {htpolynet-2.8.0 → htpolynet-2.9.0}/src/htpolynet/utils/vmd_viz.py +0 -0
  316. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/__init__.py +0 -0
  317. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/conftest.py +0 -0
  318. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/__init__.py +0 -0
  319. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/config1.gro +0 -0
  320. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/config1.top +0 -0
  321. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/config2.gro +0 -0
  322. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/config2.top +0 -0
  323. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/items31.edr +0 -0
  324. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/items43.edr +0 -0
  325. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/items45.edr +0 -0
  326. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/fixtures/short.mdp +0 -0
  327. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_bondtemplate.py +0 -0
  328. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_cap_placement.py +0 -0
  329. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_chain.py +0 -0
  330. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_configuration.py +0 -0
  331. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_convergence.py +0 -0
  332. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_dataframetools.py +0 -0
  333. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_density_gate.py +0 -0
  334. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_gpu_usability.py +0 -0
  335. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
  336. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
  337. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_inputcheck.py +0 -0
  338. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_linkcell_pierce.py +0 -0
  339. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_moleculetype_name.py +0 -0
  340. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_paramcache.py +0 -0
  341. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_paramcache_ambertools.py +0 -0
  342. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_parameterize_react.py +0 -0
  343. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_plot_smoke.py +0 -0
  344. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_projectfilesystem.py +0 -0
  345. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_relax_instrumentation.py +0 -0
  346. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_repair_conversion.py +0 -0
  347. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_resources.py +0 -0
  348. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_ring.py +0 -0
  349. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_ring_pierce_figs.py +0 -0
  350. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_setup_claude.py +0 -0
  351. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_slurm_script.py +0 -0
  352. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_smiles_input.py +0 -0
  353. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_software_provenance.py +0 -0
  354. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_topology/test.top +0 -0
  355. {htpolynet-2.8.0 → htpolynet-2.9.0}/tests/unit/test_topology.py +0 -0
@@ -7,6 +7,124 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [2.9.0] - 2026-09-15
11
+
12
+ ### Added
13
+
14
+ - **The build log reports molecules that carry net charge.** After cure,
15
+ after postcure repair, and when the final results are written, htpolynet
16
+ checks every covalently bonded molecule. It logs one line when all are
17
+ neutral to within 0.01 e, and a warning naming the count and the largest
18
+ charge when some are not. The system total is zero by construction, so
19
+ until now a template or repair step that moved charge from one molecule to
20
+ another left no trace. The check can't see charge misplaced *inside* a
21
+ percolated network, because the whole network is a single molecule.
22
+
23
+ ### Fixed
24
+
25
+ - **Later bonds on a triazine reset the charges of its earlier ones.**
26
+ Each cure template shows a single BPA on the ring, and splicing it in
27
+ rewrites the charges of atoms up to two bonds from the new bond, which
28
+ includes the other ring carbons. So every ring carbon that reacted before
29
+ the last one got its *unreacted* charge back. Example 6's fully reacted
30
+ rings had carbons anywhere from 0.14 to 0.31 e, where the template value is
31
+ 0.28. A cured bisphenol-A dicyanate network showed a clean 2:1 split,
32
+ +0.70 against +0.90 e. htpolynet now builds extra templates at setup for
33
+ rings that already carry one or two BPAs; example 6 gets 18 of them. Each
34
+ cure bond picks the one that matches the ring as it stands: templates
35
+ record which atoms two bonds from the bonding atom have already reacted,
36
+ and matching prefers the one that records the most. This applies to any
37
+ reactive atom whose `symmetry_equivalent_atoms` partners sit two bonds
38
+ away. None of the other shipped examples has one, and example 5's
39
+ build-stage molecules are unchanged, charge for charge.
40
+
41
+ Replaying example 6's recorded cure bonds offline puts every bonded ring
42
+ carbon at its template value: 0.275, 0.277 or 0.279 e for one, two or
43
+ three BPAs. All 13 molecules after cure are now neutral, where before
44
+ they ranged from -0.37 to +0.29 e. Cyanate-ester builds should be
45
+ rebuilt.
46
+
47
+ - **A template that matched a bond only in reverse crashed the cure** with
48
+ `mapping mismatch -- bug`. After reversing the bond to line up with the
49
+ template, the mapping check still compared it the original way round. No
50
+ shipped example had reached this path.
51
+
52
+ - **Cyanate-cap repair left molecules charged.** `triazine_to_cyanate_cap`
53
+ kept the system neutral, but not each molecule. It settled charge twice,
54
+ both times system-wide:
55
+ - once while splicing the cap template, when the sacrificial H's still
56
+ existed;
57
+ - once after deleting them, onto only the atoms those H's had been bonded
58
+ to.
59
+
60
+ Caps formed in place and caps transferred to a free BPA-OH therefore ended
61
+ with charges 0.24 e apart on the phenolic O and the cap C. In a
62
+ zero-conversion bisphenol-A dicyanate melt, every molecule came out at
63
+ either +0.21 or -0.27 e. In example 6, the 27 molecules left after repair
64
+ ranged from -3.59 to +0.62 e. Repair now brings each molecule it touched
65
+ back to neutral, and makes the correction only on the atoms it changed.
66
+ Example 6's molecules are all neutral, and its cap residues sit at
67
+ 0.05-0.09 e, near the template's 0.069, instead of splitting between 0.04
68
+ and 0.20. Builds that used `postcure_repair` should be rebuilt.
69
+
70
+ - **A false percolation warning on linear polymers.** The end-of-cure check
71
+ warned that too few residues had reacted at every site to assume the system
72
+ percolates, and it fired on chain-growth systems like example 1's
73
+ polystyrene -- "only 902 of 1000 STY (90.2%) ... below the 100.0% ... at its
74
+ gel point". For a difunctional monomer that threshold, `(1/(f-1))^f`, is
75
+ exactly 100%, and a fully reacted difunctional unit is a chain interior
76
+ rather than a crosslink junction, so neither the warning nor its premise
77
+ applied. The check now runs only when some residue has at least three
78
+ reactive sites.
79
+
80
+ - **The percolation check counted sites the cure never uses.** It summed
81
+ every reactive site a residue was built with, including bonds made while
82
+ assembling molecules and valences no cure reaction can consume. Example 2
83
+ warned that "0 of 150 HIE" had reacted at all four sites, which was
84
+ impossible: two of those sites sit on an atom only the molecule-building
85
+ reactions touch. Example 5's warning about TB was the same mistake, since
86
+ every TB site is a chain bond made before the cure. In examples 3 and 4 the
87
+ diepoxide and the diamine tied at four sites, so the reported fraction
88
+ mixed both residue types ("83 of 300 DGE"). Functionality and completion are
89
+ now counted only on atoms a cure reaction can bond, taken from the
90
+ symmetry-expanded reaction list the bond search itself uses. Example 3 now
91
+ reports "83 of 100 PAC", and example 6's check is unchanged. When no
92
+ residue has three or more cure sites, the check says crosslink percolation
93
+ was not assessed, rather than staying silent: systems that crosslink through
94
+ a multi-residue molecule, such as a dimethacrylate, are outside what a
95
+ residue-level count can see.
96
+
97
+ - **Bondless MOL2 files for symmetry-sibling molecules.** A molecule built by
98
+ copying a parent's topology (for example `GMAS-4`, from `GMA`) has its bonds
99
+ in the topology but no MOL2 bond table, so writing it as MOL2 produced a file
100
+ with no bonds and a "Cannot write any bonds to MOL2 file" warning -- twelve
101
+ times in example 2 on a fresh parameterization. Those writes are now filled
102
+ from the topology's bonds, as single bonds. In every shipped example the
103
+ affected files were diagnostic `*-prebonding.mol2` outputs that nothing reads,
104
+ so no parameterization input was ever affected.
105
+
106
+ - **The CPU container image failed to build for 2.8.0**, so
107
+ `ghcr.io/cameronabrams/htpolynet:v2.8.0` was never published (the CUDA image
108
+ was). The base image `condaforge/miniforge3:latest` moved to mamba 2.9.0,
109
+ whose `mamba clean -afy` fails on a symlink inside the CPU AmberTools
110
+ package. The install was succeeding; only the cleanup step failed. The
111
+ Dockerfile now cleans with `conda clean`.
112
+
113
+ ### Documentation
114
+
115
+ - **The installation page now recommends the container as the default way to
116
+ run htpolynet**, in a callout at the top with the two commands you need on a
117
+ desktop (Docker Compose) or on a cluster (Singularity/Apptainer), plus the
118
+ note that the default image is CPU-only and GPU users want the `:cuda` tag.
119
+ Installing htpolynet and its tools natively is still documented below it,
120
+ for development and for systems without containers.
121
+
122
+ - **The documentation has a logo and a landing-page illustration.** The
123
+ logo appears in every page's sidebar, in black-on-transparent for the light
124
+ theme and white-on-transparent for the dark one, so it never shows as a white
125
+ box in dark mode. The browser tab shows it too, as a favicon on a white disc
126
+ so it stays visible whether the tab bar is light or dark.
127
+
10
128
  ## [2.8.0] - 2026-09-12
11
129
 
12
130
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: htpolynet
3
- Version: 2.8.0
3
+ Version: 2.9.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,20 @@ Coverage as of the last measurement: **38.8%** overall.
199
199
 
200
200
  ## Cure and repair
201
201
 
202
+ - **Cure still settles template overcharge system-wide.**
203
+ `map_from_templates` ends each batch of bonds with one `adjust_charges`
204
+ over every mapped atom in the system. When the templates are consistent
205
+ with each other this does nothing: since the second-shell templates, all 13
206
+ of example 6's molecules after cure are neutral (before them, the
207
+ range was -0.37 to +0.29 e). But any template that does not describe
208
+ its instance exactly (a mapped atom whose context the template lacks, or
209
+ charges from a different conformer) leaks charge between molecules without
210
+ a trace. A per-molecule settle, like
211
+ `topology_surgery.neutralize_touched_fragments` in repair, would contain
212
+ it. Two cases the second-shell rule leaves out: reacted atoms *directly*
213
+ bonded to the bonding atom (it leaves those to the C=C chain machinery), and
214
+ atoms that aren't declared symmetry-equivalent.
215
+
202
216
  - **`cap_min_clearance` has never been calibrated against a working metric.**
203
217
  The 0.150 nm default was chosen in 2.6.0 against a clearance that was pinned
204
218
  at 0.136 nm by a bug, so it fired on 100 % of caps for a reason that had
@@ -905,6 +919,36 @@ Coverage as of the last measurement: **38.8%** overall.
905
919
  docs describe only the GAFF-scoped form. base.yaml declares both, marking the
906
920
  top-level spelling deprecated; pick one before the schema goes live.
907
921
 
922
+ - **A parameterized molecule built from a symmetry-sibling reactant would
923
+ hand antechamber an incomplete bond table.** Found while fixing the
924
+ bondless-MOL2 writes reported by the 2026-09-13 example sweep. Symmetry
925
+ siblings are loaded from the parent's top+gro and carry no `mol2_bonds`.
926
+ When topologies merge (`Topology.merge` via `_myconcat(... 'mol2_bonds')`),
927
+ a reactant without that table contributes nothing to the product's, so the
928
+ product's `{name}.mol2`, which `Molecule.parameterize` gives to antechamber
929
+ for atom typing, would silently lack that reactant's internal bonds.
930
+ `TopoCoord.write_mol2` now falls back to topology bonds only when the table
931
+ is absent entirely, which does not cover this partial case. Not exercised by
932
+ any shipped example: the fresh-cache 2026-09-13 sweep had zero bondless
933
+ writes outside diagnostic `-prebonding` files, and every sibling product
934
+ copied its parent's topology rather than being parameterized. The fix, if
935
+ a case ever appears, is for `merge` to synthesize `mol2_bonds` from `bonds`
936
+ for any operand that lacks the table, rather than concatenating a partial
937
+ table. Bond orders would then need the same single-bond assumption.
938
+
939
+ - **Two gaps left after the percolation check moved to cure sites
940
+ (2026-09-15).** First, a system that crosslinks through a *multi-residue*
941
+ molecule -- example 2's GMA (two methacrylate HIE units), example 5's
942
+ three-armed THT -- is reported as "not assessed". A real assessment needs a
943
+ molecule-level count: sum cure sites per molecule and ask how many molecules
944
+ reacted at all of them. Second, `CureController._completion_bias_counts`
945
+ still ranks candidates by `residue_reaction_counts` over *all* atoms, so a
946
+ bond made while building a molecule (HIE's C4) counts as progress toward
947
+ completion. That only matters with `completion_bias` on, which no shipped
948
+ example uses. It was left alone because fixing it changes which bonds a
949
+ biased cure forms, not just a diagnostic; `cure_site_mask` is the tool when
950
+ that is wanted.
951
+
908
952
  ## Simulation defaults
909
953
 
910
954
  - **The halogen constraint failure is fixed but not explained.** v2.7.0
@@ -60,12 +60,19 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
60
60
  ARG GROMACS_BUILD=
61
61
  ARG CONDA_OVERRIDE_CUDA=
62
62
 
63
+ # Clean with conda, not mamba. mamba 2.9.0 (miniforge3 26.7.2-0, the image
64
+ # :latest moved to on 2026-09-09) fails `mamba clean -afy` with "cannot get
65
+ # file size: No such file or directory" on the CPU AmberTools 26.0 package:
66
+ # its bin/amber.conda is a symlink that dangles inside the package cache, and
67
+ # mamba stats everything named *.conda. The install itself succeeds; only the
68
+ # clean dies, taking the whole RUN with it. conda clean handles the same cache
69
+ # correctly. Reproduced locally in both directions before changing this.
63
70
  RUN CONDA_OVERRIDE_CUDA="${CONDA_OVERRIDE_CUDA}" mamba install -y -n base -c conda-forge \
64
71
  ambertools \
65
72
  "gromacs${GROMACS_BUILD:+=*=${GROMACS_BUILD}*}" \
66
73
  parmed \
67
74
  rdkit \
68
- && mamba clean -afy
75
+ && conda clean -afy
69
76
 
70
77
  # Install HTPolyNet
71
78
  COPY . /htpolynet
@@ -58,6 +58,19 @@ language = 'en'
58
58
  #
59
59
  html_theme = 'furo'
60
60
 
61
+ # The logo is line art, so it ships as two transparent variants rather than one
62
+ # opaque image: black ink for the light theme, white ink for the dark one. An
63
+ # opaque logo would show as a white square in furo's dark mode.
64
+ html_theme_options = {
65
+ 'light_logo': 'htpolynet-logo-light.png',
66
+ 'dark_logo': 'htpolynet-logo-dark.png',
67
+ }
68
+
69
+ # The favicon, unlike the sidebar logo, keeps an opaque white disc: a browser's
70
+ # tab bar may be light or dark, and transparent line art would vanish on one of
71
+ # them. 16, 32 and 48 px in one .ico.
72
+ html_favicon = '_static/htpolynet-favicon.ico'
73
+
61
74
  # Add any paths that contain custom static files (such as style sheets) here,
62
75
  # relative to this directory. They are copied after the builtin static files,
63
76
  # so a file named "default.css" will overwrite the builtin "default.css".
@@ -43,6 +43,21 @@ setup time, each as a separately parameterized linked-product
43
43
  template. The cure machinery treats them as six distinct reactions in
44
44
  the iterative bond search, but the user only had to write one.
45
45
 
46
+ Six templates are not enough to give the ring the right charges,
47
+ though. Each describes a triazine with one BPA attached, so it shows
48
+ the other two ring carbons unreacted, and a template splice rewrites
49
+ the charges of every atom within two bonds of the new bond, which
50
+ includes those carbons. Without more context, the second and third
51
+ bonds on a ring would reset the carbons that reacted before them to
52
+ their unreacted charge. So htpolynet also builds, at setup time, one
53
+ template for each bonding carbon, BPA oxygen, and set of ring carbons
54
+ already bonded: 18 more, with names like
55
+ ``BPA~O1-C3~BPA~O1-C2~BPA~O1-C1~TAZ``. At each bond, the cure picks
56
+ the one that matches the ring as it stands. Nothing in the
57
+ configuration asks for these. htpolynet generates them for any
58
+ reactive atom whose ``symmetry_equivalent_atoms`` partners sit two
59
+ bonds away, as a triazine's ring carbons do.
60
+
46
61
  What the cure stage produces, then, is an A2+B3 step-growth ether
47
62
  network: every formed bond is the same chemistry (an aryl O to a
48
63
  triazine ring C, replacing one H on each side with a new C-O bond),
@@ -41,6 +41,11 @@ htpolynet
41
41
  :target: https://doi.org/10.5281/zenodo.22070252
42
42
  :alt: DOI
43
43
 
44
+ .. image:: _static/htpolynet-landing.jpg
45
+ :alt: A rusty robot in a straw hat sits on a driftwood log on a tropical beach, humming as it knots a net of ball-and-stick molecules strung between posts. A hand-painted sign beside it reads "HTPOLYNET: Stranded today. Better polymers tomorrow."
46
+ :align: center
47
+ :width: 100%
48
+
44
49
  htpolynet is a command-line tool for building atomic configurations of amorphous network polymers suitable for molecular dynamics (MD) simulations.
45
50
  It uses the General Amber Force Field and produces output that can be simulated
46
51
  using Gromacs.
@@ -2,12 +2,39 @@
2
2
  Installation and Prerequisites
3
3
  ##############################
4
4
 
5
- A pre-built container image is available that bundles all required
6
- software (Gromacs, AmberTools, OpenBabel, RDKit, and ``htpolynet``). If
7
- you have Docker or Singularity/Apptainer available, this is the easiest
8
- way to get started — see :ref:`container_usage` for instructions. The
9
- remainder of this page describes how to install ``htpolynet`` and its
10
- prerequisites directly on your system.
5
+ .. admonition:: Recommended: run htpolynet from the container
6
+ :class: tip
7
+
8
+ The easiest way to use ``htpolynet`` is the pre-built container image,
9
+ ``ghcr.io/cameronabrams/htpolynet``. It bundles everything ``htpolynet``
10
+ needs --- Gromacs, AmberTools, OpenBabel, RDKit, and ``htpolynet`` itself
11
+ --- so there is nothing else to install and no versions to line up.
12
+
13
+ **On a desktop** (Docker), fetch the Compose file once, then run
14
+ ``htpolynet`` through it:
15
+
16
+ .. code-block:: console
17
+
18
+ $ curl -O https://raw.githubusercontent.com/cameronabrams/htpolynet/main/docker/compose.yml
19
+ $ docker compose run --rm htpolynet run config.yaml
20
+
21
+ **On a cluster** (Singularity/Apptainer), pull the image once, then run it
22
+ with your working directory bound in:
23
+
24
+ .. code-block:: console
25
+
26
+ $ singularity pull htpolynet.sif docker://ghcr.io/cameronabrams/htpolynet:latest
27
+ $ singularity run --bind $(pwd):/work --pwd /work htpolynet.sif run config.yaml
28
+
29
+ The default image runs Gromacs on CPUs only. To use an NVIDIA GPU, use
30
+ the ``:cuda`` tag instead.
31
+
32
+ See :ref:`container_usage` for the details: persistent caches, GPU setup,
33
+ and pinning a release.
34
+
35
+ The rest of this page covers installing ``htpolynet`` and its prerequisites
36
+ directly on your system, which you'll want for development or wherever
37
+ containers aren't available.
11
38
 
12
39
  Software Prerequisites
13
40
  ----------------------
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "htpolynet"
7
- version = "2.8.0"
7
+ version = "2.9.0"
8
8
  authors = [
9
9
  { name="Cameron F Abrams", email="cfa22@drexel.edu" },
10
10
  ]
@@ -15,7 +15,7 @@ logger = logging.getLogger(__name__)
15
15
 
16
16
 
17
17
  class BondTemplate:
18
- def __init__(self, names, resnames, intraresidue, order, bystander_resnames, bystander_atomnames, oneaway_resnames, oneaway_atomnames):
18
+ def __init__(self, names, resnames, intraresidue, order, bystander_resnames, bystander_atomnames, oneaway_resnames, oneaway_atomnames, siblings=None):
19
19
  """Creates a BondTemplate object.
20
20
 
21
21
  Args:
@@ -27,6 +27,10 @@ class BondTemplate:
27
27
  bystander_atomnames (list of two list-like containers of strs): lists of names of atoms in bystander residues (parallel to bystander_resnames)
28
28
  oneaway_resnames (list-like container of strs): names of one-away residues (residues bound one bond away from the new interresidue bond; only relevant for C=C free-radical polymerization)
29
29
  oneaway_atomnames (list-like container of strs): names of atoms in one-away residues
30
+ siblings (list of two lists of (str, str) tuples): for each atom in names, the
31
+ (atomName, partner resName) of every other atom in its residue, within two
32
+ intraresidue bonds, that is already bonded to another residue; defaults to
33
+ none on either side. See TopoCoord.get_siblings.
30
34
  """
31
35
  self.names = names
32
36
  self.resnames = resnames
@@ -36,6 +40,7 @@ class BondTemplate:
36
40
  self.oneaway_resnames = oneaway_resnames
37
41
  self.oneaway_atomnames = oneaway_atomnames
38
42
  self.order = order
43
+ self.siblings = [sorted(tuple(t) for t in x) for x in siblings] if siblings else [[], []]
39
44
 
40
45
  def reverse(self):
41
46
  """Reverses the order of all parallel lists in a BondTemplate object."""
@@ -45,9 +50,10 @@ class BondTemplate:
45
50
  self.bystander_atomnames = self.bystander_atomnames[::-1]
46
51
  self.oneaway_resnames = self.oneaway_resnames[::-1]
47
52
  self.oneaway_atomnames = self.oneaway_atomnames[::-1]
53
+ self.siblings = self.siblings[::-1]
48
54
 
49
55
  def __str__(self):
50
- return f'BondTemplate {self.names} resnames {self.resnames} intraresidue? {self.intraresidue} order {self.order} bystander-resnames {self.bystander_resnames} bystander-atomnames {self.bystander_atomnames} oneaway-resnames {self.oneaway_resnames} oneaway-atomnames {self.oneaway_atomnames}'
56
+ return f'BondTemplate {self.names} resnames {self.resnames} intraresidue? {self.intraresidue} order {self.order} bystander-resnames {self.bystander_resnames} bystander-atomnames {self.bystander_atomnames} oneaway-resnames {self.oneaway_resnames} oneaway-atomnames {self.oneaway_atomnames} siblings {self.siblings}'
51
57
 
52
58
  def __eq__(self,other):
53
59
  check = self.names == other.names
@@ -57,6 +63,7 @@ class BondTemplate:
57
63
  check = check and self.bystander_atomnames == other.bystander_atomnames
58
64
  check = check and self.oneaway_resnames == other.oneaway_resnames
59
65
  check = check and self.oneaway_atomnames == other.oneaway_atomnames
66
+ check = check and self.siblings == other.siblings
60
67
  return check
61
68
 
62
69
  def is_reverse_of(self,other):
@@ -73,13 +80,15 @@ class BondTemplate:
73
80
  return self == rb
74
81
 
75
82
  def bystander_count(self):
76
- """Total number of bystander (resname, atomname) pairs across both sides.
83
+ """Total number of bystander (resname, atomname) pairs and siblings across both sides.
77
84
 
78
- Used by find_template's best-match selection: more bystanders = more
85
+ Used by find_template's best-match selection: more context = more
79
86
  specific template, which should win when multiple templates can match
80
- an instance under subset semantics.
87
+ an instance under subset semantics. Siblings count here so that a
88
+ triazine template with two ring carbons already bonded beats the one
89
+ with one, which beats the bare one.
81
90
  """
82
- return sum(len(s) for s in self.bystander_resnames)
91
+ return sum(len(s) for s in self.bystander_resnames) + sum(len(s) for s in self.siblings)
83
92
 
84
93
  def matches(self, other):
85
94
  """Return True if `self` (a parameterization-stage template) is a
@@ -111,6 +120,13 @@ class BondTemplate:
111
120
  force the cure reactant to mirror every inter-residue partner
112
121
  the instance carries, which forecloses the small-fragment idiom.
113
122
 
123
+ Subset semantics on siblings, for the same reason. A sibling is
124
+ another atom of a bonding residue, close enough to the bonding atom
125
+ that the template overwrites its charge, that is already bonded to
126
+ another residue. A template declaring a sibling describes that atom
127
+ as reacted, so it must not be used where the atom has not; a template
128
+ declaring none has always been used regardless, and still is.
129
+
114
130
  Args:
115
131
  other (BondTemplate): the instance bond to test for compatibility
116
132
 
@@ -133,6 +149,12 @@ class BondTemplate:
133
149
  remaining.remove(tp)
134
150
  else:
135
151
  return False
152
+ remaining = list(other.siblings[side])
153
+ for sib in self.siblings[side]:
154
+ if sib in remaining:
155
+ remaining.remove(sib)
156
+ else:
157
+ return False
136
158
  return True
137
159
 
138
160
  def matches_reverse_of(self, other):
@@ -506,7 +506,7 @@ class Molecule:
506
506
  # logger.debug(f'{self.name} oneaways {oneaway_resids} {oneaway_resnames} {oneaway_atomidx} {oneaway_atomnames}')
507
507
  self.reaction_bonds.append(ReactionBond(atom_idx, in_product_resids, order, bystander_resids, bystander_atomidx, oneaway_resids, oneaway_atomidx))
508
508
  intraresidue = in_product_resids[0] == in_product_resids[1]
509
- self.bond_templates.append(BondTemplate(atom_names, in_product_resnames, intraresidue, order, bystander_resnames, bystander_atomnames, oneaway_resnames, oneaway_atomnames))
509
+ self.bond_templates.append(BondTemplate(atom_names, in_product_resnames, intraresidue, order, bystander_resnames, bystander_atomnames, oneaway_resnames, oneaway_atomnames, siblings=TC.get_siblings(atom_idx)))
510
510
 
511
511
  def idx_mappers(self, otherTC: TopoCoord, other_bond, bystanders, oneaways, uniq_atom_idx: set):
512
512
  """Computes the mapping dictionary from molecule template index to instance index in the other TopoCoord.
@@ -23,7 +23,7 @@ from ..core.topocoord import TopoCoord
23
23
  from ..core.topology import select_topology_type_option
24
24
  from ..cure.chain import ChainManager
25
25
  from ..cure.curecontroller import CureController, CureState
26
- from ..cure.expandreactions import bondchain_expand_reactions, generate_stereo_reactions, generate_symmetry_reactions
26
+ from ..cure.expandreactions import bondchain_expand_reactions, generate_stereo_reactions, generate_symmetry_reactions, sibling_expand_reactions
27
27
  from ..cure.reaction import Reaction, ReactionList, parse_reaction_list, extract_molecule_reactions, is_reactant, reaction_stage
28
28
  from ..external import software as software
29
29
  from ..external.gromacs import insert_molecules, mdp_modify, mdp_get
@@ -320,6 +320,17 @@ class Runtime:
320
320
  self.molecules[mname]=M
321
321
  logger.debug(f'Generated {mname}')
322
322
 
323
+ new_reactions,new_molecules=sibling_expand_reactions(self.molecules,self.reactions)
324
+ if len(new_molecules)>0:
325
+ ess='' if len(new_molecules)==1 else 's'
326
+ logger.info(f'{len(new_molecules)} molecule{ess} implied by cure bonds next to already-reacted atoms')
327
+ self.reactions.extend(new_reactions)
328
+ for mname,M in new_molecules.items():
329
+ self._generate_molecule(M,force_parameterization=force_parameterization,force_checkin=force_checkin)
330
+ assert M.origin!='unparameterized'
331
+ self.molecules[mname]=M
332
+ logger.debug(f'Generated {mname}')
333
+
323
334
  for M in self.molecules:
324
335
  self.molecules[M].is_reactant=is_reactant(M,self.reactions,stage=reaction_stage.cure)
325
336
 
@@ -443,12 +454,13 @@ class Runtime:
443
454
  cure_finished=cc.is_cured()
444
455
  if not cure_finished:
445
456
  cure_finished=cc.next_iter()
446
- cc.check_iterations_vs_functionality(TC)
457
+ cc.check_iterations_vs_functionality(TC,RL,MD)
447
458
  ''' perform capping if necessary '''
448
459
  my_logger(f'Capping begins',logger.info)
449
460
  pfs.go_to(pfs.Dirs.systems_capping)
450
461
  with profiling.stage('capping'):
451
462
  cc.do_capping(TC,RL,MD,gromacs_dict=gromacs_dict)
463
+ self._report_molecule_charges('after cure')
452
464
  my_logger('Connect-Update-Relax-Equilibrate (CURE) ends',logger.info)
453
465
 
454
466
  @cp.enableCheckpoint
@@ -476,6 +488,7 @@ class Runtime:
476
488
  n_repaired, repair_stats = run_repair(TC, self.molecules, specs, self.reactions)
477
489
  my_logger(f'Postcure repair performed {n_repaired} dismantle operations', logger.info)
478
490
  self._report_repair_conversion(repair_stats)
491
+ self._report_molecule_charges('after repair')
479
492
  # Write out the repaired system so the relaxation can pick it up
480
493
  TC.write_grx_attributes('repaired.grx')
481
494
  TC.write_gro('repaired.gro')
@@ -565,6 +578,7 @@ class Runtime:
565
578
  dropped = TC.Topology.prune_stale_14_pairs()
566
579
  if dropped:
567
580
  logger.info(f'Pruned {dropped} stale [ pairs ] entries left over from cure-induced path shortening')
581
+ self._report_molecule_charges(f'in {result_name}')
568
582
  TC.write_grx_attributes(f'{result_name}.grx')
569
583
  TC.write_gro(f'{result_name}.gro')
570
584
  TC.write_top(f'{result_name}.top')
@@ -572,6 +586,37 @@ class Runtime:
572
586
  self._write_vmd_viz_files(result_name)
573
587
  return {c:os.path.basename(x) for c,x in TC.files.items() if c!='mol2'}
574
588
 
589
+ def _report_molecule_charges(self, when, tol=0.01):
590
+ """Logs whether every covalently bonded molecule in the system is neutral.
591
+
592
+ The system total is zero by construction, so a charged molecule is
593
+ otherwise invisible: a template or repair step that moves charge
594
+ between molecules leaves no other trace. A percolated network is one
595
+ molecule and neutral by construction, so this cannot see charge
596
+ misplaced inside it.
597
+
598
+ Args:
599
+ when (str): stage label for the message, e.g. 'after cure'
600
+ tol (float): largest net charge, in e, treated as neutral, defaults to 0.01
601
+
602
+ Returns:
603
+ list: (number of atoms, net charge) of each molecule carrying more than tol
604
+ """
605
+ molecules = self.TopoCoord.Topology.molecule_charges()
606
+ if not molecules:
607
+ return []
608
+ charged = [m for m in molecules if abs(m[1]) > tol]
609
+ ess = '' if len(molecules) == 1 else 's'
610
+ if not charged:
611
+ logger.info(f'Molecule charges {when}: all {len(molecules)} molecule{ess} neutral to within {tol} e')
612
+ return charged
613
+ worst = max(charged, key=lambda m: abs(m[1]))
614
+ logger.warning(f'Molecule charges {when}: {len(charged)} of {len(molecules)} molecule{ess} carry more than '
615
+ f'{tol} e of net charge; the largest is {worst[1]:+.3f} e on a {worst[0]}-atom molecule. '
616
+ f'The system total is {self.TopoCoord.Topology.total_charge():+.4f} e, so this is charge '
617
+ f'moved between molecules, which parameterization does not intend.')
618
+ return charged
619
+
575
620
  def _write_vmd_viz_files(self, result_name='final'):
576
621
  """Writes a PSF (real bond topology for VMD) and a TCL helper that
577
622
  trims bonds spanning periodic boundaries so VMD doesn't render the