htpolynet 2.3.0__tar.gz → 2.4.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.4.0/.claude/skills/htpolynet/SKILL.md +1 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.github/workflows/docker.yml +2 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/CHANGELOG.md +111 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/PKG-INFO +1 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/ROADMAP.md +116 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docker/Dockerfile +8 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +16 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/configs/configs-for-run.rst +9 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/container-usage.rst +32 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/usage.rst +35 -5
- {htpolynet-2.3.0 → htpolynet-2.4.0}/pyproject.toml +1 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/analysis/analyze.py +1 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/analysis/postsim.py +1 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cli.py +41 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/projectfilesystem.py +25 -1
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/runtime.py +19 -8
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/software.py +27 -2
- htpolynet-2.4.0/src/htpolynet/resources/claude/SKILL.md +165 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_paramcache.py +20 -4
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_projectfilesystem.py +51 -0
- htpolynet-2.4.0/tests/unit/test_setup_claude.py +64 -0
- htpolynet-2.4.0/tests/unit/test_software_provenance.py +116 -0
- htpolynet-2.3.0/.claude/skills/htpolynet/SKILL.md +0 -71
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.claude/settings.json +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.envrc +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.github/workflows/conda-forge-sync.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.github/workflows/release.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.github/workflows/test.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.gitignore +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/.readthedocs.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/CITATION.cff +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/CLAUDE.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/LICENSE +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/MANIFEST.in +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docker/compose.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docker/docker-entrypoint.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/Makefile +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/README.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/make.bat +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/requirements.txt +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/_static/.gitkeep +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/changelog.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/conf.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/htpolynetpackage.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/install.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/references/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/references/mol2-reference.pdf +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/references.bib +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/release-history.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/CURE.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/bond_filter.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/building-a-system.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/configuration-files.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/flow1.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/flow1yaml.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/hydrogenated.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/hydrogenated.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/STYCC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/bond_filter.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/hydrogenated.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/postcure-repair.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/user-guide/program-flow.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/check-conda-sync.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/release.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/render-detail.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/render-detail.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/render-snapshot.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/scripts/run_all_examples.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/analysis/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/analysis/plot.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/analysis/utils.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/bondtemplate.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/configuration.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/coordinates.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/molecule.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/paramcache.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/topocoord.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/core/topology.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cure/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cure/chain.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cure/curecontroller.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cure/expandreactions.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/cure/reaction.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/ambertools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/command.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/gromacs.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/slurm.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/external/smiles_input.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/bondlist.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/lattice.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/linkcell.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/matrix4.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/geometry/ring.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/io/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/io/gro.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/io/mol2.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/io/pdb.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/repair/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/repair/cyanate_cap.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/repair/topology_surgery.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/resources/tcl/render.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/banner.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/checkpoint.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/dataframetools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/inputcheck.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/logsetup.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/profiling.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/stringthings.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/src/htpolynet/utils/vmd_viz.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/conftest.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/config1.gro +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/config1.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/config2.gro +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/config2.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/items31.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/items43.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/items45.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/fixtures/short.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_bondtemplate.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_chain.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_configuration.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_dataframetools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_gpu_usability.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_inputcheck.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_linkcell_pierce.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_paramcache_ambertools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_parameterize_react.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_plot_smoke.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_resources.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_ring.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_ring_pierce_figs.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_slurm_script.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_smiles_input.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_topology/test.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.4.0}/tests/unit/test_topology.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
../../../src/htpolynet/resources/claude/SKILL.md
|
|
@@ -7,6 +7,117 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.4.0] - 2026-08-25
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **`htpolynet setup-claude` installs the bundled Claude Code skill**, so it
|
|
15
|
+
reaches users who `pip install` or `conda install` htpolynet rather than
|
|
16
|
+
only those working inside a clone. The skill previously lived at
|
|
17
|
+
`.claude/skills/htpolynet/`, which the tool finds only when the working
|
|
18
|
+
directory is the repository -- that is contributors, and not most users.
|
|
19
|
+
It now ships as package data and is copied to
|
|
20
|
+
`~/.claude/skills/htpolynet/SKILL.md` on request; `--skills-dir
|
|
21
|
+
./.claude/skills` scopes it to one project instead, and `--force`
|
|
22
|
+
overwrites an existing copy after an upgrade.
|
|
23
|
+
|
|
24
|
+
Nothing happens at install time: installing the package never writes to
|
|
25
|
+
`~/.claude/`. The repository's `.claude/skills/htpolynet/SKILL.md` is now
|
|
26
|
+
a symbolic link to the packaged file, so a clone and an install get the
|
|
27
|
+
same skill and the two cannot drift apart.
|
|
28
|
+
|
|
29
|
+
The skill itself was rewritten to stand alone. It used to be a router --
|
|
30
|
+
its first instruction was to read
|
|
31
|
+
`docs/source/user-guide/building-a-system.rst`, a path that does not exist
|
|
32
|
+
for an installed user -- so it now carries the procedure inline and cites
|
|
33
|
+
Read the Docs once as the full reference.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- **The container image now reports the commit it was built from.** A
|
|
38
|
+
published image had no way to say what code it contained: there is no git
|
|
39
|
+
in the image and no `.git` beside the installed package, so
|
|
40
|
+
`htpolynet info` fell back to the installed version -- which is right for
|
|
41
|
+
pip and conda and *misleading for the container*, because the weekly
|
|
42
|
+
scheduled rebuild builds from `main` HEAD and reports whatever
|
|
43
|
+
`pyproject.toml` last said. An image built four commits past a release
|
|
44
|
+
claimed to be that release, and `:latest` is the default thing people
|
|
45
|
+
pull. A user could pull `:latest`, trust the version string, and record
|
|
46
|
+
the wrong version in a methods section.
|
|
47
|
+
|
|
48
|
+
The build now passes the commit as a `HTPOLYNET_COMMIT` build argument,
|
|
49
|
+
the image carries it in its environment, and `htpolynet info` reports it
|
|
50
|
+
in preference to the version fallback. A real git checkout still wins
|
|
51
|
+
over both, since it reflects the working tree including uncommitted
|
|
52
|
+
changes. The container-usage guide explains why `:latest` moves and how
|
|
53
|
+
to pull by digest or per-commit tag when provenance has to be stateable
|
|
54
|
+
later.
|
|
55
|
+
|
|
56
|
+
- The container-usage guide now distinguishes two habits that are easy to
|
|
57
|
+
conflate: **pulling once** gives a campaign a constant tool chain, while
|
|
58
|
+
**recording the digest** is what lets you state afterwards what that tool
|
|
59
|
+
chain was. The image pins more than the htpolynet code -- Gromacs and
|
|
60
|
+
AmberTools come unpinned from conda-forge at build time, so two images
|
|
61
|
+
built days apart can carry different versions of either while running
|
|
62
|
+
identical htpolynet code.
|
|
63
|
+
|
|
64
|
+
## [2.3.1] - 2026-08-25
|
|
65
|
+
|
|
66
|
+
### Fixed
|
|
67
|
+
|
|
68
|
+
- **`htpolynet postsim` and `htpolynet analyze` no longer die in a directory
|
|
69
|
+
without a `lib/`.** Both took `-lib` with a default of `'lib'`, but only
|
|
70
|
+
`htpolynet run` creates that tree, so the default value of a flag the user
|
|
71
|
+
never typed reached `UserLibrary` and tripped its existence assertion:
|
|
72
|
+
`AssertionError: lib is not a directory`, three seconds in. The documented
|
|
73
|
+
container invocation failed on it -- running `postsim` against a staged
|
|
74
|
+
directory holding only finished results, which is the normal shape of a
|
|
75
|
+
cluster workflow, where the cure ran somewhere else.
|
|
76
|
+
|
|
77
|
+
`-lib` now defaults to nothing for these two subcommands, and the
|
|
78
|
+
conventional `./lib` is used when it happens to be there. An explicitly
|
|
79
|
+
supplied `-lib` is still validated, so a typo fails loudly rather than
|
|
80
|
+
silently degrading to no library. The assertion message now names the flag
|
|
81
|
+
and the resolved path instead of echoing a bare `lib` the user never
|
|
82
|
+
supplied.
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- Documented that **the density at the end of `postcure` is not an
|
|
87
|
+
equilibrated density**, in the `postcure` directive reference and at the
|
|
88
|
+
point in the example 6 tutorial where a reader would take a number off the
|
|
89
|
+
plot. A crosslinked network relaxes only above its glass transition, and
|
|
90
|
+
a postcure anneal peaking near *Tg* spends almost no time where the
|
|
91
|
+
network can move, so the plateau reports an under-relaxed structure
|
|
92
|
+
however long the plateau runs. Measured on four independent BPA builds:
|
|
93
|
+
the plateau gives 1.1712 +/- 0.0029 g/cm3 against 1.1983 +/- 0.0037 for
|
|
94
|
+
the same systems melted and slowly re-cooled -- 2.31% apart, with the
|
|
95
|
+
plateau 2.6-2.8% below experiment and the re-cooled value within 1%.
|
|
96
|
+
Nothing is computed incorrectly; the protocol simply does not equilibrate
|
|
97
|
+
what a reader would assume it does. The example's own anneal peak is
|
|
98
|
+
unchanged pending a test that raising it actually helps; see `ROADMAP.md`.
|
|
99
|
+
|
|
100
|
+
- `htpolynet info` no longer reports `HTPolyNet git commit: unknown` for an
|
|
101
|
+
installed copy. pip, conda and the published container have no `.git`
|
|
102
|
+
beside the package, so the lookup could never succeed and a build had no
|
|
103
|
+
way to identify its own code from inside itself -- the same question the
|
|
104
|
+
parameterization records answer for molecules. It now falls back to the
|
|
105
|
+
installed distribution version, which for a released install maps to a tag.
|
|
106
|
+
|
|
107
|
+
- The warnings about a cached parameterization with no provenance record
|
|
108
|
+
now say that the cached values are being **used**, not merely that they
|
|
109
|
+
could not be checked. The old wording ("cannot be checked against the
|
|
110
|
+
requested 'bcc' charge method") left the decisive fact implicit: the
|
|
111
|
+
build proceeds with whatever charges that entry holds. A user who
|
|
112
|
+
upgrades with an existing library, asks for `bcc` and measures `gas`
|
|
113
|
+
numbers would reasonably conclude the 2.3.0 cache guard does not work --
|
|
114
|
+
correct behavior is otherwise indistinguishable from the bug it replaced.
|
|
115
|
+
Both the per-molecule line and the stage-end block now state that the
|
|
116
|
+
build carries the cached charges, that they may not match the requested
|
|
117
|
+
method, and that this is expected for a pre-2.3 entry rather than a
|
|
118
|
+
failure. The same clarification is made in the user guide and the
|
|
119
|
+
`ambertools` directive reference.
|
|
120
|
+
|
|
10
121
|
## [2.3.0] - 2026-08-23
|
|
11
122
|
|
|
12
123
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: htpolynet
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.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/
|
|
@@ -27,6 +27,34 @@ Rough ordering within each section is by value, not by effort.
|
|
|
27
27
|
every week via the scheduled rebuild, so a run recorded as "built with
|
|
28
28
|
the container" is not reproducible. Per-commit tags already exist;
|
|
29
29
|
what's missing is documenting that users should pin one.
|
|
30
|
+
|
|
31
|
+
- **The image's Gromacs and AmberTools are unpinned, so two images with
|
|
32
|
+
identical htpolynet code can compute different numbers.** `docker/Dockerfile`
|
|
33
|
+
installs `ambertools`, `gromacs`, `parmed` and `rdkit` from conda-forge with
|
|
34
|
+
no version constraints, and the weekly rebuild exists precisely to pick up
|
|
35
|
+
whatever is newest. So the commit stamp now tells you which htpolynet
|
|
36
|
+
produced a build, and still does not tell you which force-field tool chain
|
|
37
|
+
did. Observed live: the image built 2026-08-25 carries AmberTools 26.0 and
|
|
38
|
+
Gromacs 2026.3, while panacea's native environment is on Gromacs
|
|
39
|
+
2025.4 -- a different major version against the same htpolynet.
|
|
40
|
+
|
|
41
|
+
Unpinning is deliberate and mostly right: pinning would freeze the image on
|
|
42
|
+
old Gromacs and defeat the point of a weekly rebuild. The gap is that
|
|
43
|
+
nothing *records* what a given image resolved to, so the versions are
|
|
44
|
+
discoverable only by running `htpolynet info` inside it and writing the
|
|
45
|
+
answer down by hand. The better of two candidates is an image
|
|
46
|
+
**label** carrying a `conda list` export, written at build time: `docker
|
|
47
|
+
inspect` then answers the question without running the image, so the record
|
|
48
|
+
survives reaching someone who cannot run the container at all -- a reviewer,
|
|
49
|
+
an archive, a future reader holding only the digest. The alternative, making
|
|
50
|
+
`htpolynet info` machine-readable so a build can capture it, requires the
|
|
51
|
+
image to still be runnable, which is the weaker guarantee. This is the same
|
|
52
|
+
requirement as the build manifest below, one layer further down -- what
|
|
53
|
+
produced this build, all the way to the compilers.
|
|
54
|
+
|
|
55
|
+
Raised by the calibration study, which found the 2025.4/2026.3 split only
|
|
56
|
+
because it went looking after an unrelated prompt.
|
|
57
|
+
|
|
30
58
|
- **Retire `ghcr.io/abramsgroup/htpolynet`.** Superseded by the
|
|
31
59
|
`cameronabrams` package; still public and still serving a June image to
|
|
32
60
|
anyone with an old link.
|
|
@@ -122,6 +150,29 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
122
150
|
cyanate-ester bridge series meant doing (a) and (b) by hand in a throwaway
|
|
123
151
|
RDKit script, which is exactly the work a user should not have to
|
|
124
152
|
reinvent.
|
|
153
|
+
- **Generated topologies cannot be compared byte-wise, because ParmEd
|
|
154
|
+
stamps them.** Every `.top` htpolynet writes opens with a ParmEd header
|
|
155
|
+
recording the invoking user, the host, and the date:
|
|
156
|
+
|
|
157
|
+
; File TAZ.top was generated
|
|
158
|
+
; By user: cfa (1000)
|
|
159
|
+
; On host: panacea.chemeng.drexel.edu
|
|
160
|
+
; At date: Fri. May 5 15:55:38 2026
|
|
161
|
+
|
|
162
|
+
So two physically identical parameterizations never hash the same, and the
|
|
163
|
+
obvious check -- "did these two builds produce the same parameters for the
|
|
164
|
+
shared monomers?" -- returns a false difference. The calibration study hit
|
|
165
|
+
this on its bridge series and nearly reported the series confounded on the
|
|
166
|
+
strength of an md5; the fix on their side was to strip comment lines before
|
|
167
|
+
comparing, which every user will have to reinvent. Note the header is
|
|
168
|
+
itself provenance, but the wrong kind: it records *when and where* rather
|
|
169
|
+
than *what directives*, which is what the `parm` record now covers, and it
|
|
170
|
+
actively prevents the comparison you would want. The `.itp` files carry no
|
|
171
|
+
such header and the `parm` records are JSON with sorted keys, so both
|
|
172
|
+
already compare cleanly. Worth either normalizing the `.top` header away or
|
|
173
|
+
shipping a comparison helper; this belongs with the manifest entry below,
|
|
174
|
+
since both are about being able to answer "is this the same build?".
|
|
175
|
+
|
|
125
176
|
- **`-lib` is read-only, and nothing says so.** `pfs.checkout()` and
|
|
126
177
|
`pfs.exists()` consult the `-lib` user library first, then the user cache,
|
|
127
178
|
then the system library -- but `pfs.checkin()` writes unconditionally to the
|
|
@@ -234,6 +285,71 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
234
285
|
|
|
235
286
|
## Example depot
|
|
236
287
|
|
|
288
|
+
- **Example 6's postcure anneal peaks too close to *T*:sub:`g` to relax the
|
|
289
|
+
network, and the fix is not simply "run it longer".** Measured on four
|
|
290
|
+
independent BPA builds: the postcure NPT plateau gives 1.1712 ± 0.0029
|
|
291
|
+
g/cm³ where the same systems melted and slowly re-cooled give 1.1983 ±
|
|
292
|
+
0.0037 g/cm³ -- 2.31% apart, with the plateau 2.6-2.8% below experiment
|
|
293
|
+
and the re-cooled value within 1%. The plateau is an under-relaxed
|
|
294
|
+
structure.
|
|
295
|
+
|
|
296
|
+
The mechanism, and the reason the obvious fix is the wrong one: the
|
|
297
|
+
example anneals at a 500 K peak, and the measured *T*:sub:`g` for this
|
|
298
|
+
system is 487.9 K. That is 12.1 K above the glass transition, for 80 ps.
|
|
299
|
+
The Tg ladder that produced the relaxed value spent 15,785 ps above
|
|
300
|
+
*T*:sub:`g`, peaking 112 K above it -- 197x the time, in the regime where
|
|
301
|
+
a crosslinked network actually moves. Lengthening an anneal that sits 12 K
|
|
302
|
+
above *T*:sub:`g` extends a process that barely moves anything, so the
|
|
303
|
+
lever is the peak temperature, not the duration.
|
|
304
|
+
|
|
305
|
+
**But raising the peak is unlikely to close the gap entirely.** Two
|
|
306
|
+
structures of the same network were held for 5 ns at a 480 K setpoint
|
|
307
|
+
that thermostatted to 477.1 K -- about 11 K *below* the measured
|
|
308
|
+
*T*:sub:`g`, and far longer than the 80 ps the example spends near it.
|
|
309
|
+
Relaxation there is fast at first and then stops: about 87% of an
|
|
310
|
+
initial 34.8 kg/m³ density gap -- the gap measured over the first 200 ps
|
|
311
|
+
-- closes within 3 ns, and the remaining 4.25 kg/m³ persists at
|
|
312
|
+
7.2 sigma, with a last-half trend of +0.030 kg/m³/ns, i.e. not decaying.
|
|
313
|
+
(State the baseline and the window whenever this number is quoted: the
|
|
314
|
+
same data give 83.5-87.8% across the defensible choices of each, so a
|
|
315
|
+
bare percentage is not a fact.) So heat and time buy most of the
|
|
316
|
+
relaxation quickly and then buy nothing, and a residual difference
|
|
317
|
+
survives that a longer anneal at this scale does not appear able to
|
|
318
|
+
remove. Whatever replaces the current anneal should
|
|
319
|
+
therefore be argued as a large improvement, not as a fix; an entry
|
|
320
|
+
promising equilibration would oversell what was measured.
|
|
321
|
+
|
|
322
|
+
Note what that hold also says about *T*:sub:`g` itself: **relaxation does
|
|
323
|
+
not switch off at the glass transition**, it slows continuously through
|
|
324
|
+
it. A transition 20-34 K wide by experiment means 11 K below
|
|
325
|
+
*T*:sub:`g` is inside the transition, not deep in the glass, so fast
|
|
326
|
+
early relaxation there is expected rather than anomalous. This does not
|
|
327
|
+
soften the argument above -- the 197x figure is unchanged and a peak well
|
|
328
|
+
clear of the transition is still the lever -- but it does mean *T*:sub:`g`
|
|
329
|
+
is a soft kinetic boundary for this material, which any protocol
|
|
330
|
+
expressed relative to it has to accommodate.
|
|
331
|
+
|
|
332
|
+
**Untested.** Nobody has yet built with a hotter anneal and compared it
|
|
333
|
+
against the melt-and-recool value, which is the experiment that would
|
|
334
|
+
settle it; the argument above is mechanism, not measurement. That is why
|
|
335
|
+
the example is documented rather than changed. Raising the peak also costs
|
|
336
|
+
wall-clock in a tutorial that should stay small, so the test needs to
|
|
337
|
+
report both whether it works and what it costs.
|
|
338
|
+
|
|
339
|
+
The general problem is worth more than the instance: **any protocol whose
|
|
340
|
+
relaxation depends on being above *T*:sub:`g` is fragile when *T*:sub:`g`
|
|
341
|
+
is unknown at configuration time**, which it always is -- you cannot know
|
|
342
|
+
it before building the thing. A fixed absolute peak temperature is a guess
|
|
343
|
+
that happens to be right or wrong per chemistry, silently. Something
|
|
344
|
+
expressed relative to an estimated or measured *T*:sub:`g`, or a postcure
|
|
345
|
+
that measures *T*:sub:`g` and then anneals accordingly, would be robust
|
|
346
|
+
where an absolute number is not. That is a real design change, not a
|
|
347
|
+
config edit.
|
|
348
|
+
|
|
349
|
+
Raised by the calibration study, which had already published the
|
|
350
|
+
pessimistic density before catching it -- the failure mode is reporting a
|
|
351
|
+
protocol artifact as a force-field result.
|
|
352
|
+
|
|
237
353
|
- **Example 5 is still not laptop-scale.** The `68d81fb` retune cut the
|
|
238
354
|
monomer pool to make HTPB/IPDI "fit in a reasonable wall time on a
|
|
239
355
|
laptop", but a validation run on 16 CPU cores took **10h17m** — about
|
|
@@ -51,6 +51,14 @@ COPY . /htpolynet
|
|
|
51
51
|
WORKDIR /htpolynet
|
|
52
52
|
RUN pip install --no-cache-dir .
|
|
53
53
|
|
|
54
|
+
# The commit this image was built from. There is no git in the image and no
|
|
55
|
+
# .git beside the installed package, so without this an image cannot say what
|
|
56
|
+
# code it contains -- and its version string is actively misleading between
|
|
57
|
+
# releases, since the weekly rebuild builds from main HEAD. Declared after the
|
|
58
|
+
# expensive layers so that a changed sha does not invalidate the mamba cache.
|
|
59
|
+
ARG HTPOLYNET_COMMIT=unknown
|
|
60
|
+
ENV HTPOLYNET_COMMIT=${HTPOLYNET_COMMIT}
|
|
61
|
+
|
|
54
62
|
# Pre-create HOME for the unprivileged user the entrypoint drops to. When
|
|
55
63
|
# compose.yml mounts a named volume here, Docker initializes the fresh volume
|
|
56
64
|
# from this directory and preserves the 0777 mode.
|
{htpolynet-2.3.0 → htpolynet-2.4.0}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst
RENAMED
|
@@ -87,6 +87,22 @@ Run it:
|
|
|
87
87
|
Density during annealing and equilibration
|
|
88
88
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
89
89
|
|
|
90
|
+
.. warning::
|
|
91
|
+
|
|
92
|
+
The density this stage settles at is **not** an equilibrated density.
|
|
93
|
+
This example's postcure anneal peaks at 500 K, and the measured
|
|
94
|
+
*T*:sub:`g` for this system is about 488 K -- so the anneal spends its
|
|
95
|
+
80 ps of peak time only ~12 K above the glass transition, where a
|
|
96
|
+
crosslinked network barely moves. On four independent builds the
|
|
97
|
+
postcure plateau came out 2.31% below the same systems' density after a
|
|
98
|
+
melt and slow re-cool, and 2.6-2.8% below experiment, where the
|
|
99
|
+
re-cooled value agrees with experiment to under 1%.
|
|
100
|
+
|
|
101
|
+
The 500 K peak is fine for this tutorial's purpose, which is to show the
|
|
102
|
+
workflow. It is not a basis for quoting a density. Take densities from
|
|
103
|
+
the cooling ladder below instead.
|
|
104
|
+
|
|
105
|
+
|
|
90
106
|
.. admonition:: Placeholder
|
|
91
107
|
:class: caution
|
|
92
108
|
|
|
@@ -61,7 +61,7 @@ In this section we show all subdirectives for each of the five main directives i
|
|
|
61
61
|
|
|
62
62
|
These three directives determine the parameters ``antechamber`` produces, so each parameterization records them in a ``.parm`` file checked into the library alongside its ``gro``, ``top``, ``itp``, ``tpx`` and ``grx`` files. Because the library is keyed on molecule name, that record is the only thing distinguishing a molecule parameterized one way from the same molecule parameterized another. A run whose directives disagree with the record re-parameterizes rather than reusing the cached files, and says which directives differed.
|
|
63
63
|
|
|
64
|
-
A parameterization checked in before htpolynet 2.3 has no such record. It is still used
|
|
64
|
+
A parameterization checked in before htpolynet 2.3 has no such record. It is still used **as-is**, which means the build takes whatever charges that entry holds even if they were produced with a different ``charge_method``; the run warns, per molecule and again in a block at the end of the parameterization stage, that it could not verify what produced them. This is deliberate -- it keeps an existing library working instead of re-parameterizing it wholesale -- but it does mean that asking for ``bcc`` against a pre-2.3 library can still yield ``gas`` numbers. Rebuild those entries with ``--force-parameterization`` if a build's charges need to be certain. Note that re-parameterizing after a mismatch does **not** replace the library entry unless you also pass ``--force-checkin``, so a library holding a ``gas`` parameterization keeps it even after a ``bcc`` run.
|
|
65
65
|
|
|
66
66
|
* ``GAFF``
|
|
67
67
|
|
|
@@ -263,6 +263,14 @@ In this section we show all subdirectives for each of the five main directives i
|
|
|
263
263
|
|
|
264
264
|
The ``postcure`` directive instructs ``htpolynet`` on running a series of MD simulations after cure. Its form is identical to that of ``precure``, namely with optional ``preequilibration``, ``anneal``, and ``postequilibration`` subdirectives.
|
|
265
265
|
|
|
266
|
+
.. warning::
|
|
267
|
+
|
|
268
|
+
**The density at the end of ``postequilibration`` is not an equilibrated density, and should not be quoted as one.** A crosslinked network only relaxes appreciably above its glass transition, and a postcure anneal whose peak sits near *T*:sub:`g` spends very little time where the network can move -- so the postcure plateau reports an under-relaxed structure no matter how long the plateau itself runs.
|
|
269
|
+
|
|
270
|
+
Measured on four independent BPA cyanate-ester builds: the postcure NPT plateau gave 1.1712 ± 0.0029 g/cm³ at 300 K, while the same systems melted and slowly re-cooled gave 1.1983 ± 0.0037 g/cm³ at 293 K -- a 2.31% difference between two extractions of the same quantity. Against experiment (1.205 by mercury dilatometry, 1.202 by flotation, same monomer), the plateau value is 2.6-2.8% low and the re-cooled value 0.3-0.6% low. A build reporting the plateau density would have read as a force-field failure when it was a protocol artifact.
|
|
271
|
+
|
|
272
|
+
If you need a density, extract it from a melt-and-slow-cool trajectory (an :doc:`htpolynet postsim <configs-for-postsim>` ladder does this) rather than from the postcure plateau. The same caution applies to any property that depends on the structure having relaxed.
|
|
273
|
+
|
|
266
274
|
.. _reactions:
|
|
267
275
|
|
|
268
276
|
* ``reactions``
|
|
@@ -99,6 +99,38 @@ The ``compose.yml`` file mounts the current directory into the container as
|
|
|
99
99
|
``/work`` and runs the process as your host user, so all output files are
|
|
100
100
|
written with your own ownership.
|
|
101
101
|
|
|
102
|
+
.. admonition:: Which code is in your image?
|
|
103
|
+
:class: note
|
|
104
|
+
|
|
105
|
+
``htpolynet info`` reports the exact commit the image was built from, which
|
|
106
|
+
is baked in at build time. This matters because ``:latest`` moves: besides
|
|
107
|
+
moving on every release, it is rebuilt weekly from ``main`` to pick up new
|
|
108
|
+
Gromacs and AmberTools builds, so an image tagged ``:latest`` is frequently
|
|
109
|
+
built from a commit *after* the last release and its version number alone
|
|
110
|
+
will not tell you that.
|
|
111
|
+
|
|
112
|
+
For anything whose provenance you need to be able to state later -- a
|
|
113
|
+
published result, a long campaign you want to keep consistent -- pull by
|
|
114
|
+
digest or by the per-commit tag rather than ``:latest``, and record what
|
|
115
|
+
you pulled::
|
|
116
|
+
|
|
117
|
+
$ docker pull ghcr.io/cameronabrams/htpolynet@sha256:<digest>
|
|
118
|
+
|
|
119
|
+
Every build is also pushed as ``ghcr.io/cameronabrams/htpolynet:<commit-sha>``.
|
|
120
|
+
|
|
121
|
+
Note that the image pins more than the ``htpolynet`` code. Gromacs and
|
|
122
|
+
AmberTools are installed unpinned from conda-forge at build time, so two
|
|
123
|
+
images built days apart can carry different versions of either while
|
|
124
|
+
running identical ``htpolynet`` code -- and a charge method or an
|
|
125
|
+
integrator is not something you want silently varying across a campaign.
|
|
126
|
+
Two distinct habits protect against this and are worth keeping apart:
|
|
127
|
+
**pulling once** and reusing that image gives a campaign a constant tool
|
|
128
|
+
chain, while **recording the digest** is what lets you say afterwards what
|
|
129
|
+
that tool chain was. Doing only the first leaves you consistent but unable
|
|
130
|
+
to state what you did; doing only the second leaves every fresh pull free
|
|
131
|
+
to move under you. ``htpolynet info`` prints the AmberTools and Gromacs
|
|
132
|
+
versions actually present, so record its output alongside the digest.
|
|
133
|
+
|
|
102
134
|
Running example shell scripts
|
|
103
135
|
"""""""""""""""""""""""""""""
|
|
104
136
|
|
|
@@ -21,6 +21,7 @@ Subcommand Description
|
|
|
21
21
|
``analyze`` Perform ``gmx``-style analyses of trajectories generated by post-build MD simulations
|
|
22
22
|
``gen-slurm-script`` Emit a SLURM batch script that runs ``htpolynet run`` for a given config
|
|
23
23
|
``make-viz`` Regenerate VMD visualization files (``.viz.psf`` + ``.viz.tcl``) from an existing ``top`` + ``gro`` pair
|
|
24
|
+
``setup-claude`` Install htpolynet's Claude Code skill so an agent can drive htpolynet
|
|
24
25
|
==================== ========================
|
|
25
26
|
|
|
26
27
|
``htpolynet <subcommand> -h`` provides subcommand-level help.
|
|
@@ -222,8 +223,9 @@ checked in under the same name.
|
|
|
222
223
|
.. note::
|
|
223
224
|
|
|
224
225
|
A parameterization checked in before htpolynet 2.3 carries no record.
|
|
225
|
-
Those entries are still used
|
|
226
|
-
|
|
226
|
+
Those entries are still used **as-is**, so an existing cache keeps
|
|
227
|
+
working — but the build takes whatever charges they hold, which may not
|
|
228
|
+
be what your ``charge_method`` asks for. Each one logs a warning, and
|
|
227
229
|
the parameterization stage ends with a block listing them all. Rebuild
|
|
228
230
|
them with ``--force-parameterization`` if you need certainty about what
|
|
229
231
|
a build used.
|
|
@@ -387,7 +389,9 @@ The purpose of the ``postsim`` subcommand is to control the execution of several
|
|
|
387
389
|
-h, --help show this help message and exit
|
|
388
390
|
-proj PROJ [PROJ ...]
|
|
389
391
|
name of project directory
|
|
390
|
-
-lib LIB local user library of molecular structures and
|
|
392
|
+
-lib LIB local user library of molecular structures and
|
|
393
|
+
parameterizations (default: ./lib if it exists,
|
|
394
|
+
otherwise none)
|
|
391
395
|
-ocfg OCFG original htpolynet config file used to generate project(s)
|
|
392
396
|
-cfg CFG config file specifying the operations to perform
|
|
393
397
|
--no-banner suppress the startup banner
|
|
@@ -410,7 +414,9 @@ The ``analyze`` subcommand provides a shortcut interfaces to selected ``gmx``-st
|
|
|
410
414
|
-h, --help show this help message and exit
|
|
411
415
|
-proj PROJ [PROJ ...]
|
|
412
416
|
name of project directory
|
|
413
|
-
-lib LIB local user library of molecular structures and
|
|
417
|
+
-lib LIB local user library of molecular structures and
|
|
418
|
+
parameterizations (default: ./lib if it exists,
|
|
419
|
+
otherwise none)
|
|
414
420
|
-ocfg OCFG original htpolynet config file used to generate project(s)
|
|
415
421
|
-cfg CFG config file specifying the operations to perform
|
|
416
422
|
--no-banner suppress the startup banner
|
|
@@ -506,4 +512,28 @@ The main ``.viz.tcl`` sources this file when it exists, so the macros are availa
|
|
|
506
512
|
# composable with the rest of VMD's selection language
|
|
507
513
|
mol modselect 0 top "THT and not hydrogen"
|
|
508
514
|
|
|
509
|
-
The residue-level view is untouched — selections like ``resname TBO`` or ``resname IPD`` still work — the constituent macros are an *additive* layer.
|
|
515
|
+
The residue-level view is untouched — selections like ``resname TBO`` or ``resname IPD`` still work — the constituent macros are an *additive* layer.
|
|
516
|
+
|
|
517
|
+
``htpolynet setup-claude``
|
|
518
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
519
|
+
|
|
520
|
+
``setup-claude`` installs the skill bundled with the package, which teaches Claude Code how to drive ``htpolynet``: start from the nearest example, describe monomers in their active form, check a config before spending compute, and recognize the failure modes that are known rather than mysterious.
|
|
521
|
+
|
|
522
|
+
.. code-block:: console
|
|
523
|
+
|
|
524
|
+
$ htpolynet setup-claude -h
|
|
525
|
+
|
|
526
|
+
usage: htpolynet setup-claude [-h] [--skills-dir SKILLS_DIR] [--force]
|
|
527
|
+
|
|
528
|
+
options:
|
|
529
|
+
-h, --help show this help message and exit
|
|
530
|
+
--skills-dir SKILLS_DIR
|
|
531
|
+
skills directory to install into (default: ~/.claude/skills);
|
|
532
|
+
use ./.claude/skills to scope the skill to one project
|
|
533
|
+
--force overwrite an existing installed skill
|
|
534
|
+
|
|
535
|
+
By default the skill goes to ``~/.claude/skills/htpolynet/SKILL.md``, where Claude Code finds it from any working directory. Pass ``--skills-dir ./.claude/skills`` to scope it to a single project instead.
|
|
536
|
+
|
|
537
|
+
Nothing is installed automatically: installing ``htpolynet`` never writes to ``~/.claude/``. Re-run ``setup-claude --force`` after upgrading to pick up the current version of the skill, which otherwise stays as it was when you first installed it.
|
|
538
|
+
|
|
539
|
+
Working inside a clone of the repository needs none of this --- ``.claude/skills/`` there is a symbolic link to the same file, so the skill is already in scope.
|
|
@@ -248,7 +248,7 @@ def analyze(args):
|
|
|
248
248
|
software.sw_setup()
|
|
249
249
|
logger.debug(f'ogromacs {ogromacs}')
|
|
250
250
|
for d in args.proj:
|
|
251
|
-
pfs.pfs_setup(root=os.getcwd(),topdirs=pfs.Dirs.analyze_topdirs,verbose=True,projdir=d,reProject=False,userlibrary=args.lib)
|
|
251
|
+
pfs.pfs_setup(root=os.getcwd(),topdirs=pfs.Dirs.analyze_topdirs,verbose=True,projdir=d,reProject=False,userlibrary=pfs.resolve_user_library(args.lib))
|
|
252
252
|
pfs.go_to(pfs.Dirs.analyze)
|
|
253
253
|
for stage in cfg.stagelist:
|
|
254
254
|
stage.do(**ogromacs)
|
|
@@ -436,7 +436,7 @@ def postsim(args):
|
|
|
436
436
|
software.sw_setup()
|
|
437
437
|
logger.debug(f'ogromacs {ogromacs}')
|
|
438
438
|
for d in args.proj:
|
|
439
|
-
pfs.pfs_setup(root=os.getcwd(),topdirs=pfs.Dirs.postsim_topdirs,verbose=True,projdir=d,reProject=False,userlibrary=args.lib)
|
|
439
|
+
pfs.pfs_setup(root=os.getcwd(),topdirs=pfs.Dirs.postsim_topdirs,verbose=True,projdir=d,reProject=False,userlibrary=pfs.resolve_user_library(args.lib))
|
|
440
440
|
pfs.go_to(pfs.Dirs.postsim)
|
|
441
441
|
for stage in cfg.stagelist:
|
|
442
442
|
stage.do(mdp_pfx='local',**ogromacs)
|
|
@@ -5,11 +5,15 @@ Author: Cameron F. Abrams <cfa22@drexel.edu>
|
|
|
5
5
|
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
+
import shutil
|
|
8
9
|
import textwrap
|
|
9
10
|
|
|
10
11
|
import argparse as ap
|
|
11
12
|
import yaml
|
|
12
13
|
|
|
14
|
+
from importlib.resources import files as pkg_files
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
13
17
|
from .analysis.analyze import analyze
|
|
14
18
|
from .analysis.plot import plots
|
|
15
19
|
from .analysis.postsim import postsim
|
|
@@ -119,6 +123,37 @@ def fetch_example(args):
|
|
|
119
123
|
_fetch_one(depot, fullname)
|
|
120
124
|
|
|
121
125
|
|
|
126
|
+
def setup_claude(args: ap.Namespace):
|
|
127
|
+
"""Handles the setup-claude subcommand.
|
|
128
|
+
|
|
129
|
+
Copies the bundled skill into the user's skills directory. This runs only
|
|
130
|
+
when the user asks for it; installing the package never touches
|
|
131
|
+
``~/.claude/``.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
args (argparse.Namespace): parsed arguments
|
|
135
|
+
"""
|
|
136
|
+
# Resolve through htpolynet.resources, which is a real package; the claude/
|
|
137
|
+
# subdirectory carries no __init__.py, matching every other resource
|
|
138
|
+
# subdirectory.
|
|
139
|
+
source = pkg_files('htpolynet.resources').joinpath('claude', 'SKILL.md')
|
|
140
|
+
if not source.is_file():
|
|
141
|
+
raise FileNotFoundError(f'Bundled skill not found at {source}')
|
|
142
|
+
|
|
143
|
+
skill_dir = Path(args.skills_dir).expanduser() / 'htpolynet'
|
|
144
|
+
target = skill_dir / 'SKILL.md'
|
|
145
|
+
|
|
146
|
+
if target.exists() and not args.force:
|
|
147
|
+
print(f'{target} already exists; re-run with --force to overwrite it')
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
skill_dir.mkdir(parents=True, exist_ok=True)
|
|
151
|
+
with source.open('rb') as fh, open(target, 'wb') as out:
|
|
152
|
+
shutil.copyfileobj(fh, out)
|
|
153
|
+
print(f'Written: {target}')
|
|
154
|
+
print('Claude Code picks the skill up on its next session in any directory.')
|
|
155
|
+
|
|
156
|
+
|
|
122
157
|
def _add_run_options(p, loglevel='debug'):
|
|
123
158
|
"""Adds run options (no positional config) shared by run and gen-slurm-script."""
|
|
124
159
|
p.add_argument('-lib',type=str,default='lib',help='local user library of molecular structures and parameterizations')
|
|
@@ -235,7 +270,7 @@ def _add_gen_slurm_args(p):
|
|
|
235
270
|
def _add_analysis_args(p):
|
|
236
271
|
"""Adds the common arguments shared by the postsim and analyze subcommands."""
|
|
237
272
|
p.add_argument('-proj',type=str,default='',nargs='+',help='name of project directory')
|
|
238
|
-
p.add_argument('-lib',type=str,default=
|
|
273
|
+
p.add_argument('-lib',type=str,default=None,help='local user library of molecular structures and parameterizations (default: ./lib if it exists, otherwise none)')
|
|
239
274
|
p.add_argument('-ocfg',type=str,default='',help='original htpolynet config file used to generate project(s)')
|
|
240
275
|
p.add_argument('-cfg',type=str,default='',help='config file specifying the operations to perform')
|
|
241
276
|
p.add_argument('--no-banner',default=False,action='store_true',help='suppress the startup banner')
|
|
@@ -257,6 +292,7 @@ def cli():
|
|
|
257
292
|
('analyze', analyze, "perform 'gmx <command>' style analyses specified in the config file"),
|
|
258
293
|
('gen-slurm-script', gen_slurm_script, 'generate a SLURM submission script for running htpolynet on a cluster'),
|
|
259
294
|
('make-viz', make_viz, 'regenerate VMD viz files (.viz.psf + .viz.tcl) from an existing gromacs top + gro pair'),
|
|
295
|
+
('setup-claude', setup_claude, "install htpolynet's Claude Code skill so an agent can drive htpolynet"),
|
|
260
296
|
]
|
|
261
297
|
|
|
262
298
|
parser = ap.ArgumentParser(description=textwrap.dedent(banner_message),formatter_class=ap.RawDescriptionHelpFormatter)
|
|
@@ -291,6 +327,10 @@ def cli():
|
|
|
291
327
|
cp['make-viz'].add_argument('-grx', type=str, default=None, help='input htpolynet .grx (default: auto-detect <gro-stem>.grx; needed for the constituent-selection macros)')
|
|
292
328
|
cp['make-viz'].add_argument('-prefix', type=str, default=None, help='output basename; the .viz.psf, .viz.tcl, and .viz.macros.tcl are written next to the input gro (default: stem of -gro)')
|
|
293
329
|
|
|
330
|
+
cp['setup-claude'].add_argument('--skills-dir', type=str, default='~/.claude/skills',
|
|
331
|
+
help='skills directory to install into (default: %(default)s); use ./.claude/skills to scope the skill to one project')
|
|
332
|
+
cp['setup-claude'].add_argument('--force', default=False, action='store_true', help='overwrite an existing installed skill')
|
|
333
|
+
|
|
294
334
|
_add_analysis_args(cp['postsim'])
|
|
295
335
|
_add_analysis_args(cp['analyze'])
|
|
296
336
|
|
|
@@ -208,7 +208,9 @@ class UserLibrary:
|
|
|
208
208
|
pathname (str): path to the user library directory, defaults to '.'
|
|
209
209
|
"""
|
|
210
210
|
self.root = Path(os.path.abspath(pathname))
|
|
211
|
-
assert self.root.exists() and self.root.is_dir(),
|
|
211
|
+
assert self.root.exists() and self.root.is_dir(), (
|
|
212
|
+
f'user library {pathname!r} (resolved to {self.root}) is not a directory; '
|
|
213
|
+
f'pass -lib <path> to point at an existing library, or create it')
|
|
212
214
|
|
|
213
215
|
def exists(self, filename):
|
|
214
216
|
"""Checks if filename exists in the user library.
|
|
@@ -448,6 +450,28 @@ def pfs_setup(root='.', topdirs=['molecules', 'systems', 'plots'], projdir='next
|
|
|
448
450
|
userlibrary=userlibrary, mock=mock)
|
|
449
451
|
|
|
450
452
|
|
|
453
|
+
def resolve_user_library(pathname, default='lib'):
|
|
454
|
+
"""Returns the user-library path a subcommand should use, or None for none.
|
|
455
|
+
|
|
456
|
+
An explicitly supplied path is returned unchanged, so that a typo fails
|
|
457
|
+
loudly in UserLibrary rather than silently degrading to no library. When
|
|
458
|
+
nothing was supplied, the conventional ``lib/`` is used only if it is
|
|
459
|
+
actually there: a subcommand that merely reads finished results has no
|
|
460
|
+
reason to require a molecule library, and demanding one turns the default
|
|
461
|
+
value of a flag the user never typed into a hard error.
|
|
462
|
+
|
|
463
|
+
Args:
|
|
464
|
+
pathname (str or None): the value of the ``-lib`` flag, or None if unset
|
|
465
|
+
default (str): the conventional library directory, defaults to 'lib'
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
str or None: path to use as the user library, or None for no user library
|
|
469
|
+
"""
|
|
470
|
+
if pathname is not None:
|
|
471
|
+
return pathname
|
|
472
|
+
return default if os.path.isdir(default) else None
|
|
473
|
+
|
|
474
|
+
|
|
451
475
|
def checkout(filename, altpath=[]):
|
|
452
476
|
"""Copies a file to cwd; searches user library, then user cache, then system library.
|
|
453
477
|
|