htpolynet 2.3.1__tar.gz → 2.5.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.
- htpolynet-2.5.0/.claude/skills/htpolynet/SKILL.md +1 -0
- htpolynet-2.5.0/.github/workflows/docker.yml +72 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/CHANGELOG.md +159 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/PKG-INFO +9 -6
- {htpolynet-2.3.1 → htpolynet-2.5.0}/README.md +8 -5
- {htpolynet-2.3.1 → htpolynet-2.5.0}/ROADMAP.md +166 -75
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docker/Dockerfile +34 -5
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/results.rst +17 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/install.rst +18 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/configs/configs-for-run.rst +7 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/container-usage.rst +91 -16
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/postcure-repair.rst +62 -3
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/usage.rst +26 -1
- {htpolynet-2.3.1 → htpolynet-2.5.0}/pyproject.toml +1 -1
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cli.py +40 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/runtime.py +43 -1
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cure/curecontroller.py +72 -1
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/software.py +11 -2
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/repair/__init__.py +9 -4
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/repair/cyanate_cap.py +40 -4
- htpolynet-2.5.0/src/htpolynet/resources/claude/SKILL.md +165 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +9 -1
- htpolynet-2.5.0/tests/unit/test_completion_bias.py +95 -0
- htpolynet-2.5.0/tests/unit/test_repair_conversion.py +63 -0
- htpolynet-2.5.0/tests/unit/test_setup_claude.py +64 -0
- htpolynet-2.5.0/tests/unit/test_software_provenance.py +116 -0
- htpolynet-2.3.1/.claude/skills/htpolynet/SKILL.md +0 -71
- htpolynet-2.3.1/.github/workflows/docker.yml +0 -36
- htpolynet-2.3.1/tests/unit/test_software_provenance.py +0 -61
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.claude/settings.json +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.envrc +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.github/workflows/conda-forge-sync.yml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.github/workflows/release.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.github/workflows/test.yml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.gitignore +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/.readthedocs.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/CITATION.cff +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/CLAUDE.md +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/LICENSE +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/MANIFEST.in +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docker/compose.yml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docker/docker-entrypoint.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/Makefile +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/README.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/make.bat +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/requirements.txt +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/_static/.gitkeep +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/changelog.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/conf.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/example-tutorials/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/htpolynetpackage.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/references/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/references/mol2-reference.pdf +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/references.bib +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/release-history.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/CURE.odg +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/bond_filter.odg +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/building-a-system.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/configuration-files.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/flow1.odg +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/flow1yaml.odg +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/hydrogenated.eps +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/hydrogenated.fig +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/index.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/STY.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/STYCC.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/docs/source/user-guide/program-flow.rst +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/check-conda-sync.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/release.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/render-detail.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/render-detail.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/render-snapshot.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/scripts/run_all_examples.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/analysis/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/analysis/analyze.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/analysis/plot.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/analysis/postsim.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/analysis/utils.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/bondtemplate.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/configuration.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/coordinates.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/molecule.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/paramcache.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/projectfilesystem.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/topocoord.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/core/topology.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cure/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cure/chain.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cure/expandreactions.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/cure/reaction.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/ambertools.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/command.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/gromacs.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/slurm.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/external/smiles_input.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/bondlist.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/lattice.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/linkcell.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/matrix4.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/geometry/ring.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/io/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/io/gro.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/io/mol2.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/io/pdb.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/repair/topology_surgery.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/README.md +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/README.md +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/banner.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/checkpoint.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/dataframetools.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/inputcheck.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/logsetup.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/profiling.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/stringthings.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/src/htpolynet/utils/vmd_viz.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/conftest.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/__init__.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/config1.gro +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/config1.top +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/config2.gro +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/config2.top +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/items31.edr +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/items43.edr +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/items45.edr +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/fixtures/short.mdp +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_bondtemplate.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_chain.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_configuration.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_dataframetools.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_gpu_usability.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_inputcheck.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_linkcell_pierce.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_paramcache.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_paramcache_ambertools.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_parameterize_react.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_plot_smoke.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_projectfilesystem.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_resources.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_ring.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_ring_pierce_figs.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_slurm_script.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_smiles_input.py +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_topology/test.top +0 -0
- {htpolynet-2.3.1 → htpolynet-2.5.0}/tests/unit/test_topology.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../../../src/htpolynet/resources/claude/SKILL.md
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
name: Build and push Docker image
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
- "d*"
|
|
8
|
+
schedule:
|
|
9
|
+
# Rebuild weekly (Monday 03:00 UTC) to pick up latest Gromacs/AmberTools
|
|
10
|
+
- cron: '0 3 * * 1'
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
docker:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
packages: write
|
|
18
|
+
strategy:
|
|
19
|
+
fail-fast: false
|
|
20
|
+
matrix:
|
|
21
|
+
include:
|
|
22
|
+
# The default image. conda-forge's preferred linux-64 Gromacs is the
|
|
23
|
+
# OpenCL build, which cannot drive NVIDIA devices; this image is
|
|
24
|
+
# CPU-only by design and stays the default so `docker run` on a
|
|
25
|
+
# laptop keeps working without pulling the CUDA toolkit.
|
|
26
|
+
- variant: cpu
|
|
27
|
+
gromacs_build: ""
|
|
28
|
+
cuda_override: ""
|
|
29
|
+
tag_prefix: ""
|
|
30
|
+
# The CUDA image. gromacs=*=nompi_cuda* depends on the __cuda
|
|
31
|
+
# virtual package, which conda synthesizes only where an NVIDIA
|
|
32
|
+
# driver is present -- so the solve fails on this runner unless
|
|
33
|
+
# CONDA_OVERRIDE_CUDA declares one. That makes the image buildable
|
|
34
|
+
# here; it does NOT make it verifiable here. Nothing in CI can
|
|
35
|
+
# confirm that mdrun actually offloads, so smoke-test a new CUDA
|
|
36
|
+
# image on real hardware before recommending it.
|
|
37
|
+
- variant: cuda
|
|
38
|
+
gromacs_build: "nompi_cuda"
|
|
39
|
+
cuda_override: "12.9"
|
|
40
|
+
tag_prefix: "cuda-"
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@v4
|
|
43
|
+
|
|
44
|
+
- name: Log in to GitHub Container Registry
|
|
45
|
+
uses: docker/login-action@v3
|
|
46
|
+
with:
|
|
47
|
+
registry: ghcr.io
|
|
48
|
+
username: ${{ github.actor }}
|
|
49
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
|
50
|
+
|
|
51
|
+
- name: Compute tags
|
|
52
|
+
id: tags
|
|
53
|
+
run: |
|
|
54
|
+
if [ "${{ matrix.variant }}" = "cuda" ]; then
|
|
55
|
+
moving="ghcr.io/cameronabrams/htpolynet:cuda"
|
|
56
|
+
else
|
|
57
|
+
moving="ghcr.io/cameronabrams/htpolynet:latest"
|
|
58
|
+
fi
|
|
59
|
+
printf 'tags<<EOF\n%s\nghcr.io/cameronabrams/htpolynet:%s%s\nEOF\n' \
|
|
60
|
+
"$moving" "${{ matrix.tag_prefix }}" "${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
|
61
|
+
|
|
62
|
+
- name: Build and push
|
|
63
|
+
uses: docker/build-push-action@v6
|
|
64
|
+
with:
|
|
65
|
+
context: .
|
|
66
|
+
file: docker/Dockerfile
|
|
67
|
+
push: true
|
|
68
|
+
build-args: |
|
|
69
|
+
HTPOLYNET_COMMIT=${{ github.sha }}
|
|
70
|
+
GROMACS_BUILD=${{ matrix.gromacs_build }}
|
|
71
|
+
CONDA_OVERRIDE_CUDA=${{ matrix.cuda_override }}
|
|
72
|
+
tags: ${{ steps.tags.outputs.tags }}
|
|
@@ -7,6 +7,165 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.5.0] - 2026-08-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **The conversion a cyanate-ester run reports is now the conversion the
|
|
15
|
+
structure actually carries.** The cure iterates on bond conversion --
|
|
16
|
+
bonds formed over bonds possible -- and that is the only number it printed.
|
|
17
|
+
But `postcure_repair` then dismantles every crosslinker that did not fill
|
|
18
|
+
all of its sites, so the structure leaving the repair stage contains only
|
|
19
|
+
*complete* crosslinkers, and the fraction of those is what an experiment
|
|
20
|
+
measures. For a trifunctional crosslinker under random placement the
|
|
21
|
+
second number is roughly the cube of the first, so a run at a bond
|
|
22
|
+
conversion of 0.90 leaves a cyanate conversion near 0.73 -- and nothing
|
|
23
|
+
said so. The repair stage now logs both figures side by side and writes
|
|
24
|
+
them, with the counts behind them, to `repair-summary.yaml` in the repair
|
|
25
|
+
directory.
|
|
26
|
+
|
|
27
|
+
- **`CURE.controls.completion_bias`, an opt-in change to how bond candidates
|
|
28
|
+
are ranked.** Candidates have always been ordered by pair separation
|
|
29
|
+
alone. Separation is uncorrelated with how many bonds a crosslinker
|
|
30
|
+
already carries, and the downselection that follows admits at most one bond
|
|
31
|
+
per residue per iteration, so bonds spread evenly across every crosslinker
|
|
32
|
+
in the box instead of finishing any of them. With `completion_bias: true`
|
|
33
|
+
the number of bonds already on the candidate's `B`-side residue becomes the
|
|
34
|
+
primary sort key and separation the tie-break within each group, so a
|
|
35
|
+
crosslinker with two of three sites filled is completed before an untouched
|
|
36
|
+
one is started. Nothing else about the search changes: same radius growth,
|
|
37
|
+
same dragging and relaxation, same probability application, same cycle
|
|
38
|
+
handling.
|
|
39
|
+
|
|
40
|
+
This is a modelling option, not a fix, and it is **off by default** so that
|
|
41
|
+
every existing config and every shipped example behaves exactly as before.
|
|
42
|
+
Where a partly-reacted crosslinker is a stable species the old ranking is
|
|
43
|
+
the more faithful one; where it is a reactive intermediate -- a
|
|
44
|
+
cyclotrimerizing cyanate ester, whose triazine ring either closes or does
|
|
45
|
+
not -- the new one is. Turning it on changes what `desired_conversion`
|
|
46
|
+
means physically: a config that reaches a crosslinker conversion of 0.76 at
|
|
47
|
+
`desired_conversion: 0.90` unbiased reaches about 0.90 biased, so runs
|
|
48
|
+
either side of the setting must be compared at matched crosslinker
|
|
49
|
+
conversion, not matched `desired_conversion`.
|
|
50
|
+
|
|
51
|
+
It also nearly empties the repair stage, which is worth having on its own
|
|
52
|
+
terms: repair has been seen to blow up at low conversion, where it places
|
|
53
|
+
hundreds of caps and transfers hundreds of fragments and the cap-placement
|
|
54
|
+
geometry produces atom overlaps that a step-0 minimization cannot recover
|
|
55
|
+
from. Completing crosslinkers instead of decorating them leaves it almost
|
|
56
|
+
nothing to do.
|
|
57
|
+
|
|
58
|
+
- **A CUDA image, published as `ghcr.io/cameronabrams/htpolynet:cuda`.** The
|
|
59
|
+
only image until now installed conda-forge's default linux-64 Gromacs,
|
|
60
|
+
which is an OpenCL build; Gromacs no longer drives NVIDIA devices through
|
|
61
|
+
OpenCL, so that image cannot use a GPU at all. The new tag installs
|
|
62
|
+
`gromacs=*=nompi_cuda*` from the same Dockerfile and can.
|
|
63
|
+
|
|
64
|
+
The CPU image remains `:latest` and remains the default, because the CUDA
|
|
65
|
+
build pulls in the CUDA toolkit and inflates the image substantially --
|
|
66
|
+
`docker run` on a laptop should not download a toolkit it cannot use.
|
|
67
|
+
Both tags are built by the same workflow on the same triggers, and both
|
|
68
|
+
carry the per-commit tag scheme (`:<sha>` and `:cuda-<sha>`).
|
|
69
|
+
|
|
70
|
+
`external.software.gpu_unusable_reasons()` needed no change: it already
|
|
71
|
+
reconciled detected hardware against what the gmx build can drive, so the
|
|
72
|
+
CUDA image simply starts passing checks the CPU image fails.
|
|
73
|
+
|
|
74
|
+
Verified on hardware, since nothing in CI can check this: on a Picotte
|
|
75
|
+
V100 node the image reports `GPU support: CUDA` where `:latest` reports
|
|
76
|
+
OpenCL, `htpolynet info` detects the device instead of calling it
|
|
77
|
+
`unusable`, and a complete `fetch-example 1` build ran every one of its
|
|
78
|
+
`gmx mdrun` steps with `-gpu_id 0`, using cuFFT for PME. The CUDA 12.9
|
|
79
|
+
runtime in the image runs against that node's 12.4-era driver (550.127.05)
|
|
80
|
+
under CUDA minor-version compatibility, so a site does not need a
|
|
81
|
+
bleeding-edge driver to use the tag.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- **Repair drivers now return a statistics dict rather than an operation
|
|
86
|
+
count**, and `htpolynet.repair.run_repair` returns `(total, stats)` rather
|
|
87
|
+
than a bare total. This is what carries the crosslinker-conversion figures
|
|
88
|
+
out to the runtime for reporting. Only affects code that calls a repair
|
|
89
|
+
driver directly; the `postcure_repair` config surface is unchanged.
|
|
90
|
+
|
|
91
|
+
### Fixed
|
|
92
|
+
|
|
93
|
+
- **The container documentation told users to give the image a GPU, which it
|
|
94
|
+
cannot use.** `container-usage.rst` carried a "GPU support" section
|
|
95
|
+
walking through the NVIDIA Container Toolkit and a `deploy.resources`
|
|
96
|
+
block reserving nvidia devices, ending "htpolynet will detect the
|
|
97
|
+
available GPU(s) automatically at startup" -- and then, sixty lines later
|
|
98
|
+
in the Singularity section, correctly warned that the image's conda-forge
|
|
99
|
+
Gromacs is an OpenCL build and cannot drive NVIDIA devices at all. The
|
|
100
|
+
page contradicted itself, and `README.md` repeated the wrong half with a
|
|
101
|
+
`docker run --gpus all` example.
|
|
102
|
+
|
|
103
|
+
Both now say the same thing: exposing a GPU to this image starts the
|
|
104
|
+
container and changes nothing about how it computes, so target CPU
|
|
105
|
+
partitions and do not hold a device another job could use. The reason and
|
|
106
|
+
the detection behavior are stated once, under Docker, and the HPC warning
|
|
107
|
+
points at it for the `--nv`/`--gres=gpu` specifics.
|
|
108
|
+
|
|
109
|
+
### Changed
|
|
110
|
+
|
|
111
|
+
- `htpolynet setup-claude` is now discoverable where a new user will meet
|
|
112
|
+
it: the installation page and the README, rather than only the subcommand
|
|
113
|
+
reference.
|
|
114
|
+
|
|
115
|
+
## [2.4.0] - 2026-08-25
|
|
116
|
+
|
|
117
|
+
### Added
|
|
118
|
+
|
|
119
|
+
- **`htpolynet setup-claude` installs the bundled Claude Code skill**, so it
|
|
120
|
+
reaches users who `pip install` or `conda install` htpolynet rather than
|
|
121
|
+
only those working inside a clone. The skill previously lived at
|
|
122
|
+
`.claude/skills/htpolynet/`, which the tool finds only when the working
|
|
123
|
+
directory is the repository -- that is contributors, and not most users.
|
|
124
|
+
It now ships as package data and is copied to
|
|
125
|
+
`~/.claude/skills/htpolynet/SKILL.md` on request; `--skills-dir
|
|
126
|
+
./.claude/skills` scopes it to one project instead, and `--force`
|
|
127
|
+
overwrites an existing copy after an upgrade.
|
|
128
|
+
|
|
129
|
+
Nothing happens at install time: installing the package never writes to
|
|
130
|
+
`~/.claude/`. The repository's `.claude/skills/htpolynet/SKILL.md` is now
|
|
131
|
+
a symbolic link to the packaged file, so a clone and an install get the
|
|
132
|
+
same skill and the two cannot drift apart.
|
|
133
|
+
|
|
134
|
+
The skill itself was rewritten to stand alone. It used to be a router --
|
|
135
|
+
its first instruction was to read
|
|
136
|
+
`docs/source/user-guide/building-a-system.rst`, a path that does not exist
|
|
137
|
+
for an installed user -- so it now carries the procedure inline and cites
|
|
138
|
+
Read the Docs once as the full reference.
|
|
139
|
+
|
|
140
|
+
### Fixed
|
|
141
|
+
|
|
142
|
+
- **The container image now reports the commit it was built from.** A
|
|
143
|
+
published image had no way to say what code it contained: there is no git
|
|
144
|
+
in the image and no `.git` beside the installed package, so
|
|
145
|
+
`htpolynet info` fell back to the installed version -- which is right for
|
|
146
|
+
pip and conda and *misleading for the container*, because the weekly
|
|
147
|
+
scheduled rebuild builds from `main` HEAD and reports whatever
|
|
148
|
+
`pyproject.toml` last said. An image built four commits past a release
|
|
149
|
+
claimed to be that release, and `:latest` is the default thing people
|
|
150
|
+
pull. A user could pull `:latest`, trust the version string, and record
|
|
151
|
+
the wrong version in a methods section.
|
|
152
|
+
|
|
153
|
+
The build now passes the commit as a `HTPOLYNET_COMMIT` build argument,
|
|
154
|
+
the image carries it in its environment, and `htpolynet info` reports it
|
|
155
|
+
in preference to the version fallback. A real git checkout still wins
|
|
156
|
+
over both, since it reflects the working tree including uncommitted
|
|
157
|
+
changes. The container-usage guide explains why `:latest` moves and how
|
|
158
|
+
to pull by digest or per-commit tag when provenance has to be stateable
|
|
159
|
+
later.
|
|
160
|
+
|
|
161
|
+
- The container-usage guide now distinguishes two habits that are easy to
|
|
162
|
+
conflate: **pulling once** gives a campaign a constant tool chain, while
|
|
163
|
+
**recording the digest** is what lets you state afterwards what that tool
|
|
164
|
+
chain was. The image pins more than the htpolynet code -- Gromacs and
|
|
165
|
+
AmberTools come unpinned from conda-forge at build time, so two images
|
|
166
|
+
built days apart can carry different versions of either while running
|
|
167
|
+
identical htpolynet code.
|
|
168
|
+
|
|
10
169
|
## [2.3.1] - 2026-08-25
|
|
11
170
|
|
|
12
171
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: htpolynet
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.5.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/
|
|
@@ -67,21 +67,24 @@ pip install -e .
|
|
|
67
67
|
|
|
68
68
|
Once installed, the user has access to the main ``htpolynet`` command.
|
|
69
69
|
|
|
70
|
+
If you drive htpolynet with [Claude Code](https://claude.com/claude-code), install the bundled skill so the agent knows how to use it:
|
|
71
|
+
```bash
|
|
72
|
+
htpolynet setup-claude
|
|
73
|
+
```
|
|
74
|
+
This writes `~/.claude/skills/htpolynet/SKILL.md`; nothing is installed there unless you run it.
|
|
75
|
+
|
|
70
76
|
IMPORTANT NOTES: The programs ``antechamber``, ``parmchk2`` and ``tleap`` from AmberTools must be in your path. These can be installed using the ``ambertools`` package from ``conda-forge`` or compiled from source. You also need Gromacs installed so ``gmx`` is in your path. The examples show how to build input monomer structures using OpenBabel, so to use them you need ``obabel`` in your path as well.
|
|
71
77
|
|
|
72
78
|
## Docker
|
|
73
79
|
|
|
74
|
-
As an alternative to a local installation, a prebuilt container image is published at ``ghcr.io/cameronabrams/htpolynet``. It bundles htpolynet together with Gromacs, AmberTools, and OpenBabel, so no additional dependencies are required on the host beyond Docker
|
|
80
|
+
As an alternative to a local installation, a prebuilt container image is published at ``ghcr.io/cameronabrams/htpolynet``. It bundles htpolynet together with Gromacs, AmberTools, and OpenBabel, so no additional dependencies are required on the host beyond Docker.
|
|
75
81
|
|
|
76
82
|
Run htpolynet against a configuration file in the current directory:
|
|
77
83
|
```bash
|
|
78
84
|
docker run --rm -v $(pwd):/work ghcr.io/cameronabrams/htpolynet run config.yaml
|
|
79
85
|
```
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
docker run --rm --gpus all -v $(pwd):/work ghcr.io/cameronabrams/htpolynet run config.yaml
|
|
84
|
-
```
|
|
87
|
+
**The image cannot use a GPU.** Its Gromacs comes from conda-forge, built against OpenCL rather than CUDA, and Gromacs no longer drives NVIDIA devices through OpenCL. Passing `--gpus all` starts the container and changes nothing about how it computes; on a cluster, target CPU partitions and do not request `--gres=gpu` or pass `--nv`. If you need GPU-accelerated Gromacs, install htpolynet natively against a CUDA-enabled Gromacs.
|
|
85
88
|
|
|
86
89
|
A Docker Compose file is also provided in [docker/compose.yml](docker/compose.yml) for a shorter invocation (``docker compose run --rm htpolynet run config.yaml``). See [docs/source/user-guide/container-usage.rst](docs/source/user-guide/container-usage.rst) for the full story, including Singularity/Apptainer use on HPC systems.
|
|
87
90
|
|
|
@@ -33,21 +33,24 @@ pip install -e .
|
|
|
33
33
|
|
|
34
34
|
Once installed, the user has access to the main ``htpolynet`` command.
|
|
35
35
|
|
|
36
|
+
If you drive htpolynet with [Claude Code](https://claude.com/claude-code), install the bundled skill so the agent knows how to use it:
|
|
37
|
+
```bash
|
|
38
|
+
htpolynet setup-claude
|
|
39
|
+
```
|
|
40
|
+
This writes `~/.claude/skills/htpolynet/SKILL.md`; nothing is installed there unless you run it.
|
|
41
|
+
|
|
36
42
|
IMPORTANT NOTES: The programs ``antechamber``, ``parmchk2`` and ``tleap`` from AmberTools must be in your path. These can be installed using the ``ambertools`` package from ``conda-forge`` or compiled from source. You also need Gromacs installed so ``gmx`` is in your path. The examples show how to build input monomer structures using OpenBabel, so to use them you need ``obabel`` in your path as well.
|
|
37
43
|
|
|
38
44
|
## Docker
|
|
39
45
|
|
|
40
|
-
As an alternative to a local installation, a prebuilt container image is published at ``ghcr.io/cameronabrams/htpolynet``. It bundles htpolynet together with Gromacs, AmberTools, and OpenBabel, so no additional dependencies are required on the host beyond Docker
|
|
46
|
+
As an alternative to a local installation, a prebuilt container image is published at ``ghcr.io/cameronabrams/htpolynet``. It bundles htpolynet together with Gromacs, AmberTools, and OpenBabel, so no additional dependencies are required on the host beyond Docker.
|
|
41
47
|
|
|
42
48
|
Run htpolynet against a configuration file in the current directory:
|
|
43
49
|
```bash
|
|
44
50
|
docker run --rm -v $(pwd):/work ghcr.io/cameronabrams/htpolynet run config.yaml
|
|
45
51
|
```
|
|
46
52
|
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
docker run --rm --gpus all -v $(pwd):/work ghcr.io/cameronabrams/htpolynet run config.yaml
|
|
50
|
-
```
|
|
53
|
+
**The image cannot use a GPU.** Its Gromacs comes from conda-forge, built against OpenCL rather than CUDA, and Gromacs no longer drives NVIDIA devices through OpenCL. Passing `--gpus all` starts the container and changes nothing about how it computes; on a cluster, target CPU partitions and do not request `--gres=gpu` or pass `--nv`. If you need GPU-accelerated Gromacs, install htpolynet natively against a CUDA-enabled Gromacs.
|
|
51
54
|
|
|
52
55
|
A Docker Compose file is also provided in [docker/compose.yml](docker/compose.yml) for a shorter invocation (``docker compose run --rm htpolynet run config.yaml``). See [docs/source/user-guide/container-usage.rst](docs/source/user-guide/container-usage.rst) for the full story, including Singularity/Apptainer use on HPC systems.
|
|
53
56
|
|
|
@@ -8,55 +8,57 @@ Rough ordering within each section is by value, not by effort.
|
|
|
8
8
|
|
|
9
9
|
## Container and deployment
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
11
|
+
- **The container's Gromacs is generic `AVX2_256`, on both tags.** The
|
|
12
|
+
`:cuda` image fixes the GPU half of this problem and not the SIMD half:
|
|
13
|
+
conda-forge builds for a portable baseline, so on an AVX-512 host both
|
|
14
|
+
images leave single-core throughput on the table relative to a natively
|
|
15
|
+
built or module-provided Gromacs. This is inherent to installing Gromacs
|
|
16
|
+
from conda-forge and cannot be fixed by choosing a different build string
|
|
17
|
+
-- it would take building Gromacs in the image, which trades the weekly
|
|
18
|
+
rebuild's freshness for a long build and a host-specific artifact.
|
|
19
|
+
|
|
20
|
+
Confirmed on hardware 2026-08-25: the `:cuda` image on Picotte's gpu001
|
|
21
|
+
reports `SIMD instructions: AVX2_256` on a node whose CPUs support
|
|
22
|
+
AVX-512, and Gromacs itself prints the hint that "AVX_512 ...
|
|
23
|
+
instructions will perform best on this hardware". Still unquantified, and
|
|
24
|
+
that is what would decide whether it matters: nobody has run the same
|
|
25
|
+
system against Picotte's own `abramsGrp-gromacs/2021.2/cpu-gpu` module on
|
|
26
|
+
the same node. Note Gromacs also observes that AVX2 is often the better
|
|
27
|
+
choice for runs that offload to a GPU anyway, so the penalty may be small
|
|
28
|
+
for exactly the case the `:cuda` image serves.
|
|
29
|
+
|
|
26
30
|
- **Publish a digest or version tag people can pin.** `:latest` moves
|
|
27
31
|
every week via the scheduled rebuild, so a run recorded as "built with
|
|
28
32
|
the container" is not reproducible. Per-commit tags already exist;
|
|
29
33
|
what's missing is documenting that users should pin one.
|
|
30
34
|
|
|
31
|
-
- **The
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
the
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
has correct provenance only because it pins the image by full sha
|
|
59
|
-
externally -- which remains the right practice either way.
|
|
35
|
+
- **The image's Gromacs and AmberTools are unpinned, so two images with
|
|
36
|
+
identical htpolynet code can compute different numbers.** `docker/Dockerfile`
|
|
37
|
+
installs `ambertools`, `gromacs`, `parmed` and `rdkit` from conda-forge with
|
|
38
|
+
no version constraints, and the weekly rebuild exists precisely to pick up
|
|
39
|
+
whatever is newest. So the commit stamp now tells you which htpolynet
|
|
40
|
+
produced a build, and still does not tell you which force-field tool chain
|
|
41
|
+
did. Observed live: the image built 2026-08-25 carries AmberTools 26.0 and
|
|
42
|
+
Gromacs 2026.3, while panacea's native environment is on Gromacs
|
|
43
|
+
2025.4 -- a different major version against the same htpolynet.
|
|
44
|
+
|
|
45
|
+
Unpinning is deliberate and mostly right: pinning would freeze the image on
|
|
46
|
+
old Gromacs and defeat the point of a weekly rebuild. The gap is that
|
|
47
|
+
nothing *records* what a given image resolved to, so the versions are
|
|
48
|
+
discoverable only by running `htpolynet info` inside it and writing the
|
|
49
|
+
answer down by hand. The better of two candidates is an image
|
|
50
|
+
**label** carrying a `conda list` export, written at build time: `docker
|
|
51
|
+
inspect` then answers the question without running the image, so the record
|
|
52
|
+
survives reaching someone who cannot run the container at all -- a reviewer,
|
|
53
|
+
an archive, a future reader holding only the digest. The alternative, making
|
|
54
|
+
`htpolynet info` machine-readable so a build can capture it, requires the
|
|
55
|
+
image to still be runnable, which is the weaker guarantee. This is the same
|
|
56
|
+
requirement as the build manifest below, one layer further down -- what
|
|
57
|
+
produced this build, all the way to the compilers.
|
|
58
|
+
|
|
59
|
+
Raised by the calibration study, which found the 2025.4/2026.3 split only
|
|
60
|
+
because it went looking after an unrelated prompt.
|
|
61
|
+
|
|
60
62
|
- **Retire `ghcr.io/abramsgroup/htpolynet`.** Superseded by the
|
|
61
63
|
`cameronabrams` package; still public and still serving a June image to
|
|
62
64
|
anyone with an old link.
|
|
@@ -93,6 +95,40 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
93
95
|
|
|
94
96
|
## Release and distribution
|
|
95
97
|
|
|
98
|
+
- **The release preflight cannot tell whether the *previous* release
|
|
99
|
+
actually shipped to conda-forge.** `scripts/check-conda-sync.py` compares
|
|
100
|
+
`pyproject.toml`'s runtime deps against the feedstock recipe, which
|
|
101
|
+
catches dependency drift the autotick bot cannot handle. It says nothing
|
|
102
|
+
about whether the bot's last PR ever merged. That gap ran for four
|
|
103
|
+
releases: `pip check` in the recipe's test section started failing when
|
|
104
|
+
`ambertools` began pulling in distributions with unsatisfiable metadata,
|
|
105
|
+
so the bot PRs for 2.2.0, 2.3.0, 2.3.1 and 2.4.0 all sat red and unmerged
|
|
106
|
+
while conda-forge served 2.1.0 from June. Every one of those releases
|
|
107
|
+
passed the preflight, because the deps genuinely did match. Nobody
|
|
108
|
+
noticed until a bot email got read.
|
|
109
|
+
|
|
110
|
+
Fixed on 2026-08-26 by dropping `pip check` from the recipe's test section
|
|
111
|
+
(it fails on `ambertools`' bundled distributions, never on ours) and
|
|
112
|
+
merging the 2.4.0 bump, which closed the other three. **The damage is
|
|
113
|
+
permanent and visible**: conda-forge's version list for this package now
|
|
114
|
+
reads 1.0.9 -> 2.1.0 -> 2.4.0, because 2.2.0, 2.3.0 and 2.3.1 were never
|
|
115
|
+
built there and never will be. That is worth knowing as a diagnostic in
|
|
116
|
+
its own right -- a published version list that skips releases the project
|
|
117
|
+
actually made is the retroactive signature of this failure, in any
|
|
118
|
+
package, without needing to have run any check at the time.
|
|
119
|
+
|
|
120
|
+
The check is cheap: query `api.anaconda.org/package/conda-forge/htpolynet`
|
|
121
|
+
for `latest_version` and compare it against the version being superseded.
|
|
122
|
+
A mismatch does not have to block the release -- the fix is usually on the
|
|
123
|
+
feedstock, not here -- but it must be loud, because the failure mode is
|
|
124
|
+
silence. Consider also listing open PRs on the feedstock, since a red bot
|
|
125
|
+
PR is the specific thing to look at.
|
|
126
|
+
|
|
127
|
+
The deeper point is that publishing to conda-forge is the one leg of the
|
|
128
|
+
release that completes *after* `release.sh` exits and on someone else's
|
|
129
|
+
infrastructure, so it is the only one that can fail without anything here
|
|
130
|
+
noticing.
|
|
131
|
+
|
|
96
132
|
- **External services still keyed to the old repo identity.** The Aug 2026
|
|
97
133
|
transfer from `AbramsGroup/HTPolyNet` to `cameronabrams/htpolynet` moved
|
|
98
134
|
the code but left every integration pointing at the old owner. Three
|
|
@@ -107,6 +143,12 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
107
143
|
query". Fix the RTD project URL, then activate the tagged version. Worth
|
|
108
144
|
keeping this list as the checklist if the repo ever moves again.
|
|
109
145
|
|
|
146
|
+
A fourth instance turned up on 2026-08-26 and is fixed: the conda-forge
|
|
147
|
+
recipe's `about:` block still gave `AbramsGroup/HTPolyNet` for `home` and
|
|
148
|
+
`dev_url`, and a `doc_url` of `abramsgroup.github.io/HTPolyNet` that
|
|
149
|
+
returns 404. Corrected in the same feedstock PR that unblocked the version
|
|
150
|
+
bumps.
|
|
151
|
+
|
|
110
152
|
|
|
111
153
|
- **Mint a software DOI.** Enable the Zenodo GitHub integration for
|
|
112
154
|
`cameronabrams/htpolynet`, then the next `scripts/release.sh` run
|
|
@@ -122,6 +164,55 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
122
164
|
it read `3.10 | 3.11 | 3.12 | 3.13`, which CI already verifies at both
|
|
123
165
|
ends.
|
|
124
166
|
|
|
167
|
+
## Cure and repair
|
|
168
|
+
|
|
169
|
+
- **`completion_bias` biases the `B` side only, and that is a convention,
|
|
170
|
+
not a law.** The new `CURE.controls.completion_bias` ranks bond candidates
|
|
171
|
+
by how many bonds their `B`-side residue already carries, because
|
|
172
|
+
htpolynet's A2+B3 idiom puts the multifunctional crosslinker in the `B`
|
|
173
|
+
position -- as example 6 does. A user who declares the crosslinker as `A`
|
|
174
|
+
gets no bias at all, silently, because every candidate scores zero on a
|
|
175
|
+
difunctional bridge and the ordering collapses back to distance. The
|
|
176
|
+
generalization is small (rank on the `A` side, or on the sum of both) but
|
|
177
|
+
each variant is a different physical claim about which partly-reacted
|
|
178
|
+
species is an intermediate, and none of them has been run. Do it when
|
|
179
|
+
someone has a chemistry that needs it, and make them say which side.
|
|
180
|
+
|
|
181
|
+
- **Nobody has run example 6 with `completion_bias` on.** The ranking is
|
|
182
|
+
unit-tested -- ordering, tie-breaks, missing residues, the fallback when a
|
|
183
|
+
`.grx` predates the `nreactions` attribute -- but the acceptance criteria
|
|
184
|
+
that matter are system-scale and need gmx and a multi-hour build:
|
|
185
|
+
incomplete triazines should collapse from tens to ~1 at
|
|
186
|
+
`desired_conversion: 0.90`, crosslinker conversion should rise from ~0.76
|
|
187
|
+
to ~0.90, `TAZ + CYN/3` must still equal the initial triazine count
|
|
188
|
+
exactly, and atom conservation must still be exact. If the incomplete
|
|
189
|
+
count does *not* collapse, the sort key is not surviving as far as the
|
|
190
|
+
truncation and that is where to look. Until someone runs it, the directive
|
|
191
|
+
is documented as untested at scale.
|
|
192
|
+
|
|
193
|
+
- **The repair stage's cap placement does not scale to low conversion.**
|
|
194
|
+
At a bond conversion of 0.90 the triazine-to-cyanate driver places on the
|
|
195
|
+
order of a hundred caps; at 0.30 it places hundreds and transfers hundreds
|
|
196
|
+
of fragments, and runs have died at the repair NVT with a step-0 potential
|
|
197
|
+
energy around 7e15 dominated by Lennard-Jones -- atom overlap from cap
|
|
198
|
+
placement. It is packing-dependent rather than systematic: siblings at the
|
|
199
|
+
same conversion survive. `completion_bias` makes the stage nearly empty
|
|
200
|
+
and so hides this, but the geometry is still wrong for a crowded box, and
|
|
201
|
+
a sub-gel-point study that wants the unbiased ranking will hit it again.
|
|
202
|
+
The fix is in `repair/cyanate_cap.py::_place_cyn_along` and the greedy
|
|
203
|
+
matcher around it: place against the local neighbourhood rather than along
|
|
204
|
+
the old O-H vector alone, or minimize incrementally as caps are placed.
|
|
205
|
+
|
|
206
|
+
- **`bdf.loc[:abs_max]` takes one bond more than the limit.** In
|
|
207
|
+
`curecontroller.py::_searchbonds`, the truncation that applies
|
|
208
|
+
`max_conversion_per_iteration` uses `.loc` with a slice, which is
|
|
209
|
+
inclusive of its endpoint, so an iteration limited to `n` bonds forms
|
|
210
|
+
`n + 1`. Harmless in practice -- the limit is a throttle, not a
|
|
211
|
+
correctness bound -- but it is off by one, and fixing it changes the
|
|
212
|
+
trajectory of every existing config by one bond per throttled iteration.
|
|
213
|
+
Worth doing at a version boundary where a small reproducibility break is
|
|
214
|
+
already expected, not before.
|
|
215
|
+
|
|
125
216
|
## Usability
|
|
126
217
|
|
|
127
218
|
- **`gen-slurm-script` doesn't stage to scratch.** The emitted script
|
|
@@ -152,33 +243,6 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
152
243
|
cyanate-ester bridge series meant doing (a) and (b) by hand in a throwaway
|
|
153
244
|
RDKit script, which is exactly the work a user should not have to
|
|
154
245
|
reinvent.
|
|
155
|
-
- **The bundled Claude skill only reaches people working in a clone.**
|
|
156
|
-
`.claude/skills/htpolynet/` is picked up when the working directory is the
|
|
157
|
-
repository, which covers contributors and anyone who cloned to run the
|
|
158
|
-
examples -- but not the ordinary user who `pip install`s or
|
|
159
|
-
`conda install`s htpolynet and works in their own project directory, which
|
|
160
|
-
is most of them. Whether to ship it inside the package is undecided.
|
|
161
|
-
|
|
162
|
-
Two things to settle before doing so, neither obvious:
|
|
163
|
-
|
|
164
|
-
1. **The skill would be broken as written.** Its central move is "read
|
|
165
|
-
`docs/source/user-guide/building-a-system.rst`", a repo path that does
|
|
166
|
-
not exist for an installed user. A shipped version would have to point
|
|
167
|
-
at the Read the Docs URL instead, or the guide would have to ship as
|
|
168
|
-
package data. The first is simpler and goes stale differently -- an RTD
|
|
169
|
-
link tracks `latest`, so an installed 2.3.0 would send its reader to
|
|
170
|
-
documentation for whatever is current.
|
|
171
|
-
2. **Delivery.** A skill file inside a wheel does nothing on its own;
|
|
172
|
-
something has to place it where the tool looks. An `htpolynet skill
|
|
173
|
-
--install` subcommand copying it into the user's `~/.claude/skills/`
|
|
174
|
-
is the obvious mechanism, and is also the point at which a scientific
|
|
175
|
-
package starts carrying vendor-specific tooling and an install-time
|
|
176
|
-
side effect on a directory it does not own.
|
|
177
|
-
|
|
178
|
-
Worth weighing against simply doing nothing: the procedural guide the skill
|
|
179
|
-
points at is on Read the Docs already, and an agent that reads
|
|
180
|
-
documentation gets the same content without any of this.
|
|
181
|
-
|
|
182
246
|
- **Generated topologies cannot be compared byte-wise, because ParmEd
|
|
183
247
|
stamps them.** Every `.top` htpolynet writes opens with a ParmEd header
|
|
184
248
|
recording the invoking user, the host, and the date:
|
|
@@ -326,10 +390,37 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
326
390
|
example anneals at a 500 K peak, and the measured *T*:sub:`g` for this
|
|
327
391
|
system is 487.9 K. That is 12.1 K above the glass transition, for 80 ps.
|
|
328
392
|
The Tg ladder that produced the relaxed value spent 15,785 ps above
|
|
329
|
-
*T*:sub:`g`, peaking 112 K above it -- 197x the time, in the
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
393
|
+
*T*:sub:`g`, peaking 112 K above it -- 197x the time, in the regime where
|
|
394
|
+
a crosslinked network actually moves. Lengthening an anneal that sits 12 K
|
|
395
|
+
above *T*:sub:`g` extends a process that barely moves anything, so the
|
|
396
|
+
lever is the peak temperature, not the duration.
|
|
397
|
+
|
|
398
|
+
**But raising the peak is unlikely to close the gap entirely.** Two
|
|
399
|
+
structures of the same network were held for 5 ns at a 480 K setpoint
|
|
400
|
+
that thermostatted to 477.1 K -- about 11 K *below* the measured
|
|
401
|
+
*T*:sub:`g`, and far longer than the 80 ps the example spends near it.
|
|
402
|
+
Relaxation there is fast at first and then stops: about 87% of an
|
|
403
|
+
initial 34.8 kg/m³ density gap -- the gap measured over the first 200 ps
|
|
404
|
+
-- closes within 3 ns, and the remaining 4.25 kg/m³ persists at
|
|
405
|
+
7.2 sigma, with a last-half trend of +0.030 kg/m³/ns, i.e. not decaying.
|
|
406
|
+
(State the baseline and the window whenever this number is quoted: the
|
|
407
|
+
same data give 83.5-87.8% across the defensible choices of each, so a
|
|
408
|
+
bare percentage is not a fact.) So heat and time buy most of the
|
|
409
|
+
relaxation quickly and then buy nothing, and a residual difference
|
|
410
|
+
survives that a longer anneal at this scale does not appear able to
|
|
411
|
+
remove. Whatever replaces the current anneal should
|
|
412
|
+
therefore be argued as a large improvement, not as a fix; an entry
|
|
413
|
+
promising equilibration would oversell what was measured.
|
|
414
|
+
|
|
415
|
+
Note what that hold also says about *T*:sub:`g` itself: **relaxation does
|
|
416
|
+
not switch off at the glass transition**, it slows continuously through
|
|
417
|
+
it. A transition 20-34 K wide by experiment means 11 K below
|
|
418
|
+
*T*:sub:`g` is inside the transition, not deep in the glass, so fast
|
|
419
|
+
early relaxation there is expected rather than anomalous. This does not
|
|
420
|
+
soften the argument above -- the 197x figure is unchanged and a peak well
|
|
421
|
+
clear of the transition is still the lever -- but it does mean *T*:sub:`g`
|
|
422
|
+
is a soft kinetic boundary for this material, which any protocol
|
|
423
|
+
expressed relative to it has to accommodate.
|
|
333
424
|
|
|
334
425
|
**Untested.** Nobody has yet built with a hotter anneal and compared it
|
|
335
426
|
against the melt-and-recool value, which is the experiment that would
|