htpolynet 2.2.0__tar.gz → 2.3.1__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.3.1/.claude/skills/htpolynet/SKILL.md +71 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/CHANGELOG.md +149 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/CITATION.cff +6 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/PKG-INFO +2 -1
- {htpolynet-2.2.0 → htpolynet-2.3.1}/README.md +1 -0
- htpolynet-2.3.1/ROADMAP.md +373 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +16 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/htpolynetpackage.rst +5 -0
- htpolynet-2.3.1/docs/source/user-guide/building-a-system.rst +172 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-run.rst +14 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/index.rst +1 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/usage.rst +50 -11
- {htpolynet-2.2.0 → htpolynet-2.3.1}/pyproject.toml +1 -1
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/analyze.py +1 -1
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/postsim.py +1 -1
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cli.py +2 -2
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/molecule.py +7 -0
- htpolynet-2.3.1/src/htpolynet/core/paramcache.py +132 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/projectfilesystem.py +26 -2
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/runtime.py +118 -7
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/ambertools.py +23 -4
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/software.py +18 -2
- htpolynet-2.3.1/tests/unit/test_paramcache.py +342 -0
- htpolynet-2.3.1/tests/unit/test_paramcache_ambertools.py +198 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_projectfilesystem.py +51 -0
- htpolynet-2.3.1/tests/unit/test_software_provenance.py +61 -0
- htpolynet-2.2.0/ROADMAP.md +0 -116
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.claude/settings.json +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.envrc +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/conda-forge-sync.yml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/docker.yml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/release.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.github/workflows/test.yml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.gitignore +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/.readthedocs.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/CLAUDE.md +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/LICENSE +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/MANIFEST.in +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/Dockerfile +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/compose.yml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docker/docker-entrypoint.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/Makefile +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/README.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/make.bat +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/requirements.txt +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/_static/.gitkeep +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/changelog.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/conf.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-equil-rho_v_ns.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/example-tutorials/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/install.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references/index.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references/mol2-reference.pdf +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/references.bib +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/release-history.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/CURE.odg +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/bond_filter.odg +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/configuration-files.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/container-usage.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1.odg +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1yaml.odg +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.eps +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.fig +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STY.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STYCC.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/bond_filter.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/hydrogenated.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/postcure-repair.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/docs/source/user-guide/program-flow.rst +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/check-conda-sync.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/release.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-detail.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-detail.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/render-snapshot.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/scripts/run_all_examples.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/plot.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/analysis/utils.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/bondtemplate.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/configuration.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/coordinates.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/topocoord.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/core/topology.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/chain.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/curecontroller.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/expandreactions.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/cure/reaction.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/command.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/gromacs.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/slurm.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/external/smiles_input.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/bondlist.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/lattice.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/linkcell.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/matrix4.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/geometry/ring.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/gro.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/mol2.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/io/pdb.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/cyanate_cap.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/repair/topology_surgery.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/README.md +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/README.md +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/min.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/npt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/render.tcl +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/banner.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/checkpoint.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/dataframetools.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/inputcheck.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/logsetup.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/profiling.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/stringthings.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/src/htpolynet/utils/vmd_viz.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/conftest.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/__init__.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.gro +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.top +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.gro +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.top +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items31.edr +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items43.edr +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/items45.edr +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/fixtures/short.mdp +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_bondtemplate.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_chain.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_configuration.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_dataframetools.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gpu_usability.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_inputcheck.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_linkcell_pierce.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_parameterize_react.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_plot_smoke.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_resources.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_ring.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_ring_pierce_figs.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_slurm_script.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_smiles_input.py +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_topology/test.top +0 -0
- {htpolynet-2.2.0 → htpolynet-2.3.1}/tests/unit/test_topology.py +0 -0
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: htpolynet
|
|
3
|
+
description: Build crosslinked polymer systems with htpolynet — authoring a run configuration, parameterizing monomers, running a cure, and reading the results. Use when the task involves an htpolynet YAML config, the `htpolynet` command (run, input-check, gen-slurm-script, plots, postsim, analyze, make-viz), a monomer's active form or sacrificial hydrogens, a cure that stalls below its target conversion, or sizing an htpolynet build for a cluster.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Working with htpolynet
|
|
7
|
+
|
|
8
|
+
**Read `docs/source/user-guide/building-a-system.rst` first.** It is the
|
|
9
|
+
procedure, start to finish, and it is maintained alongside the code. This
|
|
10
|
+
file exists to route you there and to carry the few things that are easy to
|
|
11
|
+
get wrong before you get that far. Do not restate the docs here; when they
|
|
12
|
+
and this file disagree, the docs are right.
|
|
13
|
+
|
|
14
|
+
## Start from an example, never from an empty file
|
|
15
|
+
|
|
16
|
+
`htpolynet fetch-example <n>` unpacks a working configuration. Pick the one
|
|
17
|
+
closest in **reaction topology** — chain growth, A2+B3 step growth,
|
|
18
|
+
cyclotrimerization — not the one closest in chemistry. Adapt it. Writing a
|
|
19
|
+
config from scratch is the slowest route and the one that produces silent
|
|
20
|
+
errors.
|
|
21
|
+
|
|
22
|
+
Run the example unmodified once before editing, to confirm the toolchain and
|
|
23
|
+
to get a known-good log to diff against.
|
|
24
|
+
|
|
25
|
+
## Monomers are described in their active form
|
|
26
|
+
|
|
27
|
+
The most common conceptual error, and it produces a build that completes and
|
|
28
|
+
is wrong rather than one that fails. htpolynet conserves valence: bonding
|
|
29
|
+
atoms each give up a sacrificial hydrogen, so you describe the monomer with
|
|
30
|
+
its reactive sites already saturated. Styrene is described as ethylbenzene.
|
|
31
|
+
See `docs/source/user-guide/molecular-structure-inputs.rst`.
|
|
32
|
+
|
|
33
|
+
In SMILES bracket atoms the hydrogen count is explicit: `[C:1]` means *zero*
|
|
34
|
+
implicit hydrogens. For an sp³ carbon you almost always want `[CH2:1]` or
|
|
35
|
+
`[CH3:1]`. A wrong count usually surfaces much later as a missing GAFF angle
|
|
36
|
+
parameter in `tleap`.
|
|
37
|
+
|
|
38
|
+
## Subcommand routing
|
|
39
|
+
|
|
40
|
+
| Intent | Command |
|
|
41
|
+
|---|---|
|
|
42
|
+
| Build a system | `htpolynet run <cfg>` |
|
|
43
|
+
| Size it before queueing | `htpolynet input-check <cfg>` |
|
|
44
|
+
| Stop after parameterization | `htpolynet run --param-only <cfg>` |
|
|
45
|
+
| Submit to a cluster | `htpolynet gen-slurm-script <cfg>` |
|
|
46
|
+
| Plot a finished build | `htpolynet plots build --proj <dir>` |
|
|
47
|
+
| Post-build MD / analysis | `htpolynet postsim`, `htpolynet analyze` |
|
|
48
|
+
| Rebuild VMD viz files | `htpolynet make-viz` |
|
|
49
|
+
| Report the environment | `htpolynet info` |
|
|
50
|
+
|
|
51
|
+
## Non-obvious facts
|
|
52
|
+
|
|
53
|
+
- **The container image cannot use a GPU.** Its Gromacs is conda-forge,
|
|
54
|
+
built against OpenCL, which Gromacs no longer uses for NVIDIA devices.
|
|
55
|
+
Target CPU partitions; never suggest `--gres=gpu` or `--nv`.
|
|
56
|
+
- **Size core requests from `htpolynet input-check`**, which reports the
|
|
57
|
+
initial atom count.
|
|
58
|
+
- **A cure stalling below its target conversion** is usually a reaction
|
|
59
|
+
template that never matches — suspect `symmetry_equivalent_atoms` and
|
|
60
|
+
reactive-atom names before suspecting the chemistry.
|
|
61
|
+
- **Builds are not reproducible run to run.** There is no seed control, so
|
|
62
|
+
replicas come free but an exact rebuild does not. Record the commit.
|
|
63
|
+
|
|
64
|
+
## Do not
|
|
65
|
+
|
|
66
|
+
- Do not write workarounds into this file. If the tool surprises a user in a
|
|
67
|
+
way that requires a ritual to avoid, that is a bug: fix it in code, or file
|
|
68
|
+
it in `ROADMAP.md` with enough context to act on later. A skill that
|
|
69
|
+
teaches people to route around a defect keeps the defect.
|
|
70
|
+
- Do not hand-roll a release, a version bump, or a `CHANGELOG` rotation; see
|
|
71
|
+
`CLAUDE.md`.
|
|
@@ -7,6 +7,155 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.3.1] - 2026-08-25
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`htpolynet postsim` and `htpolynet analyze` no longer die in a directory
|
|
15
|
+
without a `lib/`.** Both took `-lib` with a default of `'lib'`, but only
|
|
16
|
+
`htpolynet run` creates that tree, so the default value of a flag the user
|
|
17
|
+
never typed reached `UserLibrary` and tripped its existence assertion:
|
|
18
|
+
`AssertionError: lib is not a directory`, three seconds in. The documented
|
|
19
|
+
container invocation failed on it -- running `postsim` against a staged
|
|
20
|
+
directory holding only finished results, which is the normal shape of a
|
|
21
|
+
cluster workflow, where the cure ran somewhere else.
|
|
22
|
+
|
|
23
|
+
`-lib` now defaults to nothing for these two subcommands, and the
|
|
24
|
+
conventional `./lib` is used when it happens to be there. An explicitly
|
|
25
|
+
supplied `-lib` is still validated, so a typo fails loudly rather than
|
|
26
|
+
silently degrading to no library. The assertion message now names the flag
|
|
27
|
+
and the resolved path instead of echoing a bare `lib` the user never
|
|
28
|
+
supplied.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- Documented that **the density at the end of `postcure` is not an
|
|
33
|
+
equilibrated density**, in the `postcure` directive reference and at the
|
|
34
|
+
point in the example 6 tutorial where a reader would take a number off the
|
|
35
|
+
plot. A crosslinked network relaxes only above its glass transition, and
|
|
36
|
+
a postcure anneal peaking near *Tg* spends almost no time where the
|
|
37
|
+
network can move, so the plateau reports an under-relaxed structure
|
|
38
|
+
however long the plateau runs. Measured on four independent BPA builds:
|
|
39
|
+
the plateau gives 1.1712 +/- 0.0029 g/cm3 against 1.1983 +/- 0.0037 for
|
|
40
|
+
the same systems melted and slowly re-cooled -- 2.31% apart, with the
|
|
41
|
+
plateau 2.6-2.8% below experiment and the re-cooled value within 1%.
|
|
42
|
+
Nothing is computed incorrectly; the protocol simply does not equilibrate
|
|
43
|
+
what a reader would assume it does. The example's own anneal peak is
|
|
44
|
+
unchanged pending a test that raising it actually helps; see `ROADMAP.md`.
|
|
45
|
+
|
|
46
|
+
- `htpolynet info` no longer reports `HTPolyNet git commit: unknown` for an
|
|
47
|
+
installed copy. pip, conda and the published container have no `.git`
|
|
48
|
+
beside the package, so the lookup could never succeed and a build had no
|
|
49
|
+
way to identify its own code from inside itself -- the same question the
|
|
50
|
+
parameterization records answer for molecules. It now falls back to the
|
|
51
|
+
installed distribution version, which for a released install maps to a tag.
|
|
52
|
+
|
|
53
|
+
- The warnings about a cached parameterization with no provenance record
|
|
54
|
+
now say that the cached values are being **used**, not merely that they
|
|
55
|
+
could not be checked. The old wording ("cannot be checked against the
|
|
56
|
+
requested 'bcc' charge method") left the decisive fact implicit: the
|
|
57
|
+
build proceeds with whatever charges that entry holds. A user who
|
|
58
|
+
upgrades with an existing library, asks for `bcc` and measures `gas`
|
|
59
|
+
numbers would reasonably conclude the 2.3.0 cache guard does not work --
|
|
60
|
+
correct behavior is otherwise indistinguishable from the bug it replaced.
|
|
61
|
+
Both the per-molecule line and the stage-end block now state that the
|
|
62
|
+
build carries the cached charges, that they may not match the requested
|
|
63
|
+
method, and that this is expected for a pre-2.3 entry rather than a
|
|
64
|
+
failure. The same clarification is made in the user guide and the
|
|
65
|
+
`ambertools` directive reference.
|
|
66
|
+
|
|
67
|
+
## [2.3.0] - 2026-08-23
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- **A cached parameterization is no longer reused for a run that asked for
|
|
72
|
+
different AmberTools directives.** `molecules/parameterized` is keyed on
|
|
73
|
+
molecule name alone, and nothing in that key reflected the charge method.
|
|
74
|
+
A configuration specifying `charge_method: bcc` therefore reused, without
|
|
75
|
+
warning, a `gas` parameterization checked into the user library under the
|
|
76
|
+
same residue name, logging only `Using cached parameterization for TAZ`.
|
|
77
|
+
Measured on a cyanate-ester triazine, the cached `gas` entry carries ring
|
|
78
|
+
C +0.1185 / N -0.2249 where a real `bcc` run gives +0.6539 / -0.7160 --
|
|
79
|
+
5.5x on the charge of the crosslink node -- and the result was a network
|
|
80
|
+
built with `bcc` on one monomer and Gasteiger on another, with nothing in
|
|
81
|
+
the output recording it. The failure was silent and invalidated results
|
|
82
|
+
without failing the build.
|
|
83
|
+
|
|
84
|
+
Each parameterization now writes a `.parm` record beside its
|
|
85
|
+
gro/top/itp/tpx/grx files listing the `charge_method`, `net_charge` and
|
|
86
|
+
`atom_type` that produced it, and that record is checked into the library
|
|
87
|
+
with them. A run whose directives disagree with the record treats the
|
|
88
|
+
cache as a miss and re-parameterizes, saying which directives differed.
|
|
89
|
+
|
|
90
|
+
A library entry written before this release carries no record. Those are
|
|
91
|
+
still used -- an existing library keeps working rather than
|
|
92
|
+
re-parameterizing wholesale -- but each one logs a warning naming the
|
|
93
|
+
charge method that could not be verified, and the parameterization stage
|
|
94
|
+
ends with a block listing every such molecule and the count. Rebuild them
|
|
95
|
+
with `--force-parameterization` if you need certainty about what a build
|
|
96
|
+
used.
|
|
97
|
+
|
|
98
|
+
Re-parameterizing after a mismatch checks its output in only under
|
|
99
|
+
`--force-checkin`, so a library entry is never silently replaced by one
|
|
100
|
+
built with different directives.
|
|
101
|
+
|
|
102
|
+
### Added
|
|
103
|
+
|
|
104
|
+
- `ambertools.net_charge` and `ambertools.atom_type` configuration
|
|
105
|
+
directives, defaulting to `0` and `gaff`. The net charge was previously
|
|
106
|
+
hardcoded as `-nc 0` in the antechamber invocation, so an ionic or
|
|
107
|
+
zwitterionic monomer was parameterized as though it were neutral with no
|
|
108
|
+
way to say otherwise. The defaults reproduce the previous commands
|
|
109
|
+
exactly.
|
|
110
|
+
|
|
111
|
+
- A procedural page in the user guide, **Building a System, Start to
|
|
112
|
+
Finish**. The guide was strong on reference and had nothing on order of
|
|
113
|
+
operations: start from the nearest bundled example rather than an empty
|
|
114
|
+
file, describe monomers in their active form, check what you can before
|
|
115
|
+
spending compute, and a short list of failures that are known rather than
|
|
116
|
+
mysterious. It states plainly what `input-check` does not yet verify and
|
|
117
|
+
that there is no seed control, so builds are not reproducible run to run.
|
|
118
|
+
|
|
119
|
+
- A Claude skill (`.claude/skills/htpolynet/`) for users working in a clone
|
|
120
|
+
of the repository. It routes to the guide rather than restating it, and
|
|
121
|
+
carries the subcommand table and the handful of facts that are easy to get
|
|
122
|
+
wrong early.
|
|
123
|
+
|
|
124
|
+
- Test coverage for the parameterization record: 34 tests comparing records
|
|
125
|
+
without external tools, and 6 that run antechamber under both charge
|
|
126
|
+
methods to confirm the record describes what actually ran, that the
|
|
127
|
+
directive it guards changes the charges, and that a library holding a
|
|
128
|
+
`gas` entry refuses a `bcc` request while still reusing it for a `gas`
|
|
129
|
+
one. The latter skip when the AmberTools chain is absent.
|
|
130
|
+
|
|
131
|
+
### Changed
|
|
132
|
+
|
|
133
|
+
- The `-lib` description in the user guide corrected. It said htpolynet
|
|
134
|
+
would "check-in the results of parameterized molecules ... in
|
|
135
|
+
`lib/molecules/parameterized`", which is false: `-lib` governs lookup
|
|
136
|
+
only, and check-in always goes to the per-user cache at `~/.htpolynet`
|
|
137
|
+
(or `$HTPOLYNET_CACHE`). A user who set `-lib` expecting to contain a
|
|
138
|
+
run's output was not contained, and nothing announced the writes.
|
|
139
|
+
`HTPOLYNET_CACHE` is now documented as the variable that actually governs
|
|
140
|
+
where products land.
|
|
141
|
+
|
|
142
|
+
- The user guide's "Parameterization caching" section corrected to match the
|
|
143
|
+
new behavior. It stated that a stale entry is silently reused when you
|
|
144
|
+
change "SMILES, atom-naming, or charge method" and that the cache is
|
|
145
|
+
"keyed by molecule name only"; the charge-method half of the first and all
|
|
146
|
+
of the second are no longer true. The warning now covers exactly what the
|
|
147
|
+
record does not: a constituent's structure, atom-naming or geometry
|
|
148
|
+
changing without a rename.
|
|
149
|
+
|
|
150
|
+
- `--force-checkin`'s help text corrected. It said "force check-in of
|
|
151
|
+
generated parameter files to the system library", which reads as though
|
|
152
|
+
check-in happens only when the flag is given. It does not: a molecule
|
|
153
|
+
whose name the library does not yet hold is checked in either way, and the
|
|
154
|
+
flag governs only whether an entry already there is *overwritten*. It
|
|
155
|
+
also named the wrong library -- check-in goes to the per-user library at
|
|
156
|
+
`~/.htpolynet` (or `$HTPOLYNET_CACHE`), not the system library. Behavior
|
|
157
|
+
is unchanged.
|
|
158
|
+
|
|
10
159
|
## [2.2.0] - 2026-08-23
|
|
11
160
|
|
|
12
161
|
### Changed
|
|
@@ -18,6 +18,12 @@ authors:
|
|
|
18
18
|
email: cfa22@drexel.edu
|
|
19
19
|
affiliation: Drexel University
|
|
20
20
|
repository-code: https://github.com/cameronabrams/htpolynet
|
|
21
|
+
identifiers:
|
|
22
|
+
- type: doi
|
|
23
|
+
value: 10.5281/zenodo.22070252
|
|
24
|
+
description: >-
|
|
25
|
+
Concept DOI for htpolynet; always resolves to the latest
|
|
26
|
+
archived release.
|
|
21
27
|
url: https://htpolynet.readthedocs.io/
|
|
22
28
|
license: MIT
|
|
23
29
|
version: 2.1.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: htpolynet
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.3.1
|
|
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/
|
|
@@ -42,6 +42,7 @@ Description-Content-Type: text/markdown
|
|
|
42
42
|
[](https://github.com/cameronabrams/htpolynet/blob/main/LICENSE)
|
|
43
43
|
[](https://htpolynet.readthedocs.io/en/latest/)
|
|
44
44
|
[](https://pepy.tech/projects/htpolynet)
|
|
45
|
+
[](https://doi.org/10.5281/zenodo.22070252)
|
|
45
46
|
|
|
46
47
|
htpolynet is a Python utility for generating atomistic models of cross-linked polymer networks together with appropriate topology and parameter files required for molecular dynamics simulations using Gromacs. It is intended as a fully automated system builder requiring as inputs only the molecular structures of any monomer species, a description of the polymerization chemistry, and a handful of options describing desired system size and composition. htpolynet uses the Generalized Amber Force Field for atom-typing and parameter generation.
|
|
47
48
|
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://github.com/cameronabrams/htpolynet/blob/main/LICENSE)
|
|
9
9
|
[](https://htpolynet.readthedocs.io/en/latest/)
|
|
10
10
|
[](https://pepy.tech/projects/htpolynet)
|
|
11
|
+
[](https://doi.org/10.5281/zenodo.22070252)
|
|
11
12
|
|
|
12
13
|
htpolynet is a Python utility for generating atomistic models of cross-linked polymer networks together with appropriate topology and parameter files required for molecular dynamics simulations using Gromacs. It is intended as a fully automated system builder requiring as inputs only the molecular structures of any monomer species, a description of the polymerization chemistry, and a handful of options describing desired system size and composition. htpolynet uses the Generalized Amber Force Field for atom-typing and parameter generation.
|
|
13
14
|
|
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
Ideas worth doing that we haven't done yet. This is a living list, not a
|
|
4
|
+
commitment or a schedule. When something here gets done, it moves to
|
|
5
|
+
`CHANGELOG.md` and comes off this page.
|
|
6
|
+
|
|
7
|
+
Rough ordering within each section is by value, not by effort.
|
|
8
|
+
|
|
9
|
+
## Container and deployment
|
|
10
|
+
|
|
11
|
+
- **CUDA-enabled Gromacs in the container image.** The published image
|
|
12
|
+
installs Gromacs from conda-forge, whose default linux-64 package is
|
|
13
|
+
built with OpenCL (not CUDA) and generic `AVX2_256` SIMD. Gromacs no
|
|
14
|
+
longer drives NVIDIA devices through OpenCL, so the image cannot use a
|
|
15
|
+
GPU at all, and on an AVX-512 host it also leaves single-core
|
|
16
|
+
throughput on the table. For reference, Picotte's own module is
|
|
17
|
+
`AVX_512` + CUDA. Doing this well probably means a second image tag
|
|
18
|
+
(e.g. `:cuda`) built against `gromacs=*=nompi_cuda*` rather than
|
|
19
|
+
changing the default, since it pulls in the CUDA runtime and inflates
|
|
20
|
+
the image substantially, and it needs a GPU-equipped runner or a
|
|
21
|
+
manual build to verify. The CPU image should stay the default so that
|
|
22
|
+
`docker run` on a laptop keeps working. Note that
|
|
23
|
+
`software.gpu_unusable_reasons()` already reasons about this correctly,
|
|
24
|
+
so a CUDA image would simply start passing its checks rather than
|
|
25
|
+
needing new logic.
|
|
26
|
+
- **Publish a digest or version tag people can pin.** `:latest` moves
|
|
27
|
+
every week via the scheduled rebuild, so a run recorded as "built with
|
|
28
|
+
the container" is not reproducible. Per-commit tags already exist;
|
|
29
|
+
what's missing is documenting that users should pin one.
|
|
30
|
+
|
|
31
|
+
- **The container cannot report which commit built it, and its version
|
|
32
|
+
string is actively misleading between releases.** `htpolynet info` used to
|
|
33
|
+
print `git commit: unknown` inside the image, because `_get_git_commit()`
|
|
34
|
+
runs `git rev-parse` against the installed package directory and no
|
|
35
|
+
installed copy has a `.git` beside it. That now falls back to the
|
|
36
|
+
installed distribution version, which is right for a pip or conda install
|
|
37
|
+
and *precisely wrong for the container*: the scheduled rebuild builds from
|
|
38
|
+
`main` HEAD, which can be many commits past the last tag, so the image
|
|
39
|
+
reports its `pyproject.toml` version honestly while running code that is
|
|
40
|
+
not that version.
|
|
41
|
+
|
|
42
|
+
This is live, not hypothetical. The 2026-08-24 03:54 scheduled build moved
|
|
43
|
+
`:latest` to an image built from `948c301` -- four commits past `v2.3.0`
|
|
44
|
+
-- and that image reports `installed version 2.3.0`. `:latest` is the
|
|
45
|
+
default thing a user pulls and the weekly cron is what keeps moving it, so
|
|
46
|
+
the wrong answer is the common case, and it is wrong silently. A user
|
|
47
|
+
could pull `:latest`, trust the version string, and write "htpolynet
|
|
48
|
+
2.3.0" in a methods section while having run untagged `main`.
|
|
49
|
+
|
|
50
|
+
The fix is to bake the real commit in at image build time -- the build
|
|
51
|
+
context has `.git`, so `docker.yml` or the Dockerfile can capture
|
|
52
|
+
`git rev-parse HEAD` and write it where the package can read it. That
|
|
53
|
+
touches the Dockerfile and the release story together, which is why it was
|
|
54
|
+
kept out of the bugfix that added the version fallback. It belongs with
|
|
55
|
+
the build-manifest entry below: both answer "what produced this build",
|
|
56
|
+
and a manifest that recorded an unreliable version string would launder
|
|
57
|
+
the problem rather than solve it. Raised by the calibration study, which
|
|
58
|
+
has correct provenance only because it pins the image by full sha
|
|
59
|
+
externally -- which remains the right practice either way.
|
|
60
|
+
- **Retire `ghcr.io/abramsgroup/htpolynet`.** Superseded by the
|
|
61
|
+
`cameronabrams` package; still public and still serving a June image to
|
|
62
|
+
anyone with an old link.
|
|
63
|
+
|
|
64
|
+
## Testing and CI
|
|
65
|
+
|
|
66
|
+
Coverage as of the last measurement: **38.8%** overall.
|
|
67
|
+
|
|
68
|
+
- **`repair/` has no tests at all** — `cyanate_cap.py` (208 statements)
|
|
69
|
+
and `topology_surgery.py` (125), both at 0%. This is the highest-value
|
|
70
|
+
gap: the postcure repair stage makes the strongest correctness claim in
|
|
71
|
+
the project ("atom conservation is exact"), and right now the only
|
|
72
|
+
thing checking it is reading a residue census at the end of a
|
|
73
|
+
multi-hour build. It is pure topology manipulation, so it can be tested
|
|
74
|
+
deterministically in milliseconds against a synthetic `TopoCoord`
|
|
75
|
+
carrying triazines at k=0,1,2,3 — assert atom counts, the residue
|
|
76
|
+
census, cap placement, and that no unreacted bridge -OH survives.
|
|
77
|
+
- **An end-to-end example in CI.** A deliberately tiny build (a
|
|
78
|
+
20-molecule, few-ps variant of example 0) run inside the container
|
|
79
|
+
would cover `core/runtime.py` and `cure/curecontroller.py` — 1,056
|
|
80
|
+
statements, both at 0% — in the only way that is honest, since faking
|
|
81
|
+
the whole AmberTools/Gromacs tool chain to unit-test the orchestration
|
|
82
|
+
is a large effort for less confidence.
|
|
83
|
+
- **Remaining zero-coverage modules**: `analysis/postsim.py` (203),
|
|
84
|
+
`cli.py` (165), `analysis/analyze.py` (137), `utils/vmd_viz.py` (75),
|
|
85
|
+
`utils/checkpoint.py` (54).
|
|
86
|
+
- **`analysis/plot.py` is at 34%** after the smoke-test pass. The
|
|
87
|
+
diagnostics-log parsers (`diagnostics_graphs`, `_token_match`,
|
|
88
|
+
`_parse_data`) are the part most likely to rot silently — they already
|
|
89
|
+
broke once when modules were renamed — and they are testable against a
|
|
90
|
+
small captured log fixture.
|
|
91
|
+
- **Coverage reporting in CI**, so the number is visible on a PR rather
|
|
92
|
+
than something we remember to measure by hand.
|
|
93
|
+
|
|
94
|
+
## Release and distribution
|
|
95
|
+
|
|
96
|
+
- **External services still keyed to the old repo identity.** The Aug 2026
|
|
97
|
+
transfer from `AbramsGroup/HTPolyNet` to `cameronabrams/htpolynet` moved
|
|
98
|
+
the code but left every integration pointing at the old owner. Three
|
|
99
|
+
broke and were fixed during the 2.2.0 release: the GHCR package path
|
|
100
|
+
(docs referenced a package that had never been published under the new
|
|
101
|
+
owner), PyPI trusted publishing (`invalid-publisher` — the claim no
|
|
102
|
+
longer matched, so the v2.2.0 upload failed until the publisher was
|
|
103
|
+
re-registered), and Read the Docs, whose project `repository.url` is
|
|
104
|
+
**still** `https://github.com/AbramsGroup/htpolynet`. Builds succeed
|
|
105
|
+
anyway because GitHub redirects the clone, but tag versions never sync —
|
|
106
|
+
`/en/v2.2.0/` 404s and the API reports "No Version matches the given
|
|
107
|
+
query". Fix the RTD project URL, then activate the tagged version. Worth
|
|
108
|
+
keeping this list as the checklist if the repo ever moves again.
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
- **Mint a software DOI.** Enable the Zenodo GitHub integration for
|
|
112
|
+
`cameronabrams/htpolynet`, then the next `scripts/release.sh` run
|
|
113
|
+
archives the release automatically. Afterwards, add the concept DOI (not
|
|
114
|
+
the version DOI) as a README badge and an `identifiers` entry in
|
|
115
|
+
`CITATION.cff`. Note that enabling is not retroactive: releases before
|
|
116
|
+
the toggle are not archived. Also note that adding a `.zenodo.json`
|
|
117
|
+
would make Zenodo ignore `CITATION.cff` entirely — only worth doing if
|
|
118
|
+
we need Zenodo-specific fields such as `grants` for funder linkage.
|
|
119
|
+
- **Per-minor Python classifiers.** `pyproject.toml` declares only
|
|
120
|
+
`Programming Language :: Python :: 3`, so the PyPI Python badge reads an
|
|
121
|
+
uninformative `python: 3`. Adding `:: 3.10` through `:: 3.13` would make
|
|
122
|
+
it read `3.10 | 3.11 | 3.12 | 3.13`, which CI already verifies at both
|
|
123
|
+
ends.
|
|
124
|
+
|
|
125
|
+
## Usability
|
|
126
|
+
|
|
127
|
+
- **`gen-slurm-script` doesn't stage to scratch.** The emitted script
|
|
128
|
+
runs in the submit directory. A cure run does heavy small-file I/O
|
|
129
|
+
every iteration, so on a cluster whose home and group storage are NFS
|
|
130
|
+
that is the wrong place. The cluster-correct pattern is to run in
|
|
131
|
+
node-local or parallel scratch and copy results back, with a `trap` so
|
|
132
|
+
partial results survive a timeout. It also cannot emit a job array,
|
|
133
|
+
which is the right shape for sweeping a set of configs.
|
|
134
|
+
- **`-restart` is documented as "EXPERIMENTAL: broken at the cure
|
|
135
|
+
stage".** A build that dies mid-cure currently has to start over — the
|
|
136
|
+
worst possible time to lose work, since cure is the longest stage.
|
|
137
|
+
- **Make `input-check` a real config linter.** It currently reports only
|
|
138
|
+
the initial atom count. Everything a new config gets wrong is checkable
|
|
139
|
+
cheaply and statically, before the user spends hours discovering it:
|
|
140
|
+
(a) that each `symmetry_equivalent_atoms` group really is topologically
|
|
141
|
+
equivalent — RDKit canonical ranks with `breakTies=False` settle it in
|
|
142
|
+
about ten lines, and a wrong group silently generates reaction templates
|
|
143
|
+
the cure stage will never match; (b) that the A2+B3 site counts actually
|
|
144
|
+
balance at the given monomer `count`s, and that `desired_conversion` is
|
|
145
|
+
reachable given them; (c) that no `reactive_atoms` name collides with the
|
|
146
|
+
bare element names `_reset_names_to_element` assigns to every unmapped
|
|
147
|
+
atom, since the repair stage looks atoms up by name; (d) that the
|
|
148
|
+
requested `charge_method` matches the provenance record of any cached
|
|
149
|
+
parameterization of the same name -- the build itself now rejects a
|
|
150
|
+
mismatch, but reporting it in the pre-flight is cheaper than discovering
|
|
151
|
+
mid-run that half the molecules need re-parameterizing. Building the
|
|
152
|
+
cyanate-ester bridge series meant doing (a) and (b) by hand in a throwaway
|
|
153
|
+
RDKit script, which is exactly the work a user should not have to
|
|
154
|
+
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
|
+
- **Generated topologies cannot be compared byte-wise, because ParmEd
|
|
183
|
+
stamps them.** Every `.top` htpolynet writes opens with a ParmEd header
|
|
184
|
+
recording the invoking user, the host, and the date:
|
|
185
|
+
|
|
186
|
+
; File TAZ.top was generated
|
|
187
|
+
; By user: cfa (1000)
|
|
188
|
+
; On host: panacea.chemeng.drexel.edu
|
|
189
|
+
; At date: Fri. May 5 15:55:38 2026
|
|
190
|
+
|
|
191
|
+
So two physically identical parameterizations never hash the same, and the
|
|
192
|
+
obvious check -- "did these two builds produce the same parameters for the
|
|
193
|
+
shared monomers?" -- returns a false difference. The calibration study hit
|
|
194
|
+
this on its bridge series and nearly reported the series confounded on the
|
|
195
|
+
strength of an md5; the fix on their side was to strip comment lines before
|
|
196
|
+
comparing, which every user will have to reinvent. Note the header is
|
|
197
|
+
itself provenance, but the wrong kind: it records *when and where* rather
|
|
198
|
+
than *what directives*, which is what the `parm` record now covers, and it
|
|
199
|
+
actively prevents the comparison you would want. The `.itp` files carry no
|
|
200
|
+
such header and the `parm` records are JSON with sorted keys, so both
|
|
201
|
+
already compare cleanly. Worth either normalizing the `.top` header away or
|
|
202
|
+
shipping a comparison helper; this belongs with the manifest entry below,
|
|
203
|
+
since both are about being able to answer "is this the same build?".
|
|
204
|
+
|
|
205
|
+
- **`-lib` is read-only, and nothing says so.** `pfs.checkout()` and
|
|
206
|
+
`pfs.exists()` consult the `-lib` user library first, then the user cache,
|
|
207
|
+
then the system library -- but `pfs.checkin()` writes unconditionally to the
|
|
208
|
+
user cache, and `UserLibrary` has no `checkin()` method at all. So pointing
|
|
209
|
+
a run at `-lib somewhere` redirects where it *reads* parameterizations from
|
|
210
|
+
while leaving where it *writes* them untouched. That asymmetry is invisible
|
|
211
|
+
from the flag, from `--help`, and from the docs, and it is a natural thing
|
|
212
|
+
to get wrong: a user who passes `-lib` for provenance reasonably concludes
|
|
213
|
+
their products are being contained there. Either `checkin()` should prefer
|
|
214
|
+
the user library when one is configured, or the flag and docs should say
|
|
215
|
+
plainly that it governs lookup only. Verified empirically 2026-08-23: with
|
|
216
|
+
`userlibrary` set, `pfs.checkin()` still landed the file in the user cache.
|
|
217
|
+
|
|
218
|
+
What makes this more than a naming problem is that the writes are silent
|
|
219
|
+
and cumulative. Nothing logs them, nothing warns, and a run that is
|
|
220
|
+
quietly depositing molecules into a shared library looks identical to one
|
|
221
|
+
that is not -- the only way to discover it is to audit mtimes, which
|
|
222
|
+
nobody does unprompted. The calibration study ran three sweeps believing
|
|
223
|
+
`-lib` contained it, and would have added roughly seventy entries to
|
|
224
|
+
`~/.htpolynet` across its remaining bridges; it was caught by reading
|
|
225
|
+
`checkin()`, not by anything the tool said. Whatever the fix, a run should
|
|
226
|
+
be able to say where its parameterizations went -- which is the same
|
|
227
|
+
requirement as the build manifest below, approached from the write side
|
|
228
|
+
rather than the read side. The two may well be one item: *where did this
|
|
229
|
+
come from, and what produced it*.
|
|
230
|
+
|
|
231
|
+
- **No way to run without writing to the user library.** `pfs.checkin()`
|
|
232
|
+
declines to *replace* an entry unless `--force-checkin` is given, but it
|
|
233
|
+
always *writes* one the library does not yet hold, so any run adds every
|
|
234
|
+
molecule name it produces to `~/.htpolynet`. The flag's help text said
|
|
235
|
+
"force check-in of generated parameter files to the system library", which
|
|
236
|
+
reads as though check-in happens only with the flag, and it named the wrong
|
|
237
|
+
library; that wording is fixed, but the missing capability is real. The
|
|
238
|
+
calibration study wanted exactly this: a way to develop against a config
|
|
239
|
+
without its intermediate products accumulating in a library shared with
|
|
240
|
+
other work. Today the only lever is pointing `HTPOLYNET_CACHE` elsewhere,
|
|
241
|
+
which is a blunt instrument because it also hides the entries you *do* want
|
|
242
|
+
to reuse. A `--no-checkin` flag threaded through
|
|
243
|
+
`Runtime._checkin_parameterization()` would cover it in a few lines.
|
|
244
|
+
|
|
245
|
+
- **Two different defaults for `charge_method`.** `AMBERTOOLS_DEFAULTS` in
|
|
246
|
+
`external/ambertools.py` says `bcc`, which is what a direct
|
|
247
|
+
`GAFFParameterize()` call with no directives gets; `Runtime.runtime_defaults`
|
|
248
|
+
says `gas`, which is what every actual build gets, because
|
|
249
|
+
`_apply_runtime_defaults()` fills it in before AmberTools is ever reached.
|
|
250
|
+
Both were already there and the provenance record is consistent either way
|
|
251
|
+
-- whichever default applies is the one recorded -- so this is a
|
|
252
|
+
readability trap rather than a live bug. It is still worth collapsing to
|
|
253
|
+
one value, and the answer is probably `gas`, since changing what builds
|
|
254
|
+
default to would silently change everyone's charges, which is the exact
|
|
255
|
+
class of harm the record was added to prevent.
|
|
256
|
+
|
|
257
|
+
- **Nothing durable records that a build reused parameterizations of
|
|
258
|
+
unverified provenance.** The parameterization stage now warns per molecule
|
|
259
|
+
and again in a block at the end of the stage, but both live only in the
|
|
260
|
+
log, and a log is the first thing discarded. Someone reading a result six
|
|
261
|
+
months later -- or a reviewer asking what a published network was actually
|
|
262
|
+
parameterized with -- has no artifact to check. htpolynet writes no build
|
|
263
|
+
manifest today; `profile.json` holds timings only, and the diagnostic log
|
|
264
|
+
is the log. A small `build-manifest.json` in the project directory listing
|
|
265
|
+
each molecule, its origin (`newly parameterized` / `previously
|
|
266
|
+
parameterized`), and its provenance record where one exists would carry
|
|
267
|
+
that, and would be worth more than this one flag: it is also the natural
|
|
268
|
+
home for the config hash, the htpolynet and AmberTools versions, and the
|
|
269
|
+
seed once seeds exist. Raised by the calibration study, which caught the
|
|
270
|
+
original cache bug from a wall-clock anomaly rather than from any log line.
|
|
271
|
+
See also the `-lib` entry above: "a run should be able to say where its
|
|
272
|
+
parameterizations went" and "a result should be able to say what produced
|
|
273
|
+
it" are the same requirement from two directions, and a manifest that
|
|
274
|
+
recorded the check-in destination would answer both.
|
|
275
|
+
|
|
276
|
+
- **A cached parameterization is not checked against the input structure
|
|
277
|
+
it was built from.** The provenance record added alongside the cache now
|
|
278
|
+
covers `charge_method`, `net_charge` and `atom_type` -- everything in the
|
|
279
|
+
AmberTools invocation -- but not the structure antechamber consumed. So
|
|
280
|
+
editing `lib/molecules/inputs/TAZ.mol2` and re-running still reuses the
|
|
281
|
+
parameterization of the *old* geometry, silently, exactly as the charge
|
|
282
|
+
method used to. Hashing the input would close it, and for a monomer that
|
|
283
|
+
is easy: `Molecule.parameterize()` has the input file in the working
|
|
284
|
+
directory at the moment it runs. Two things stopped it going in with the
|
|
285
|
+
rest: (a) a molecule built by a reaction has no stable input to hash --
|
|
286
|
+
`generate()` writes its mol2 from the merged reactant TopoCoord, whose
|
|
287
|
+
coordinates vary run to run, so hashing it would make every generated
|
|
288
|
+
molecule a permanent cache miss; the hash would have to be recorded only
|
|
289
|
+
for `origin == 'unparameterized'` monomers and compared only when both
|
|
290
|
+
sides carry one. (b) `Runtime._cached_parameterization_mismatch()` runs
|
|
291
|
+
before `generate()` checks the input structure out, and `pfs` has no way
|
|
292
|
+
to resolve a library file to an absolute path without copying it into the
|
|
293
|
+
working directory -- `checkout()` always copies. A `pfs.locate(filename)`
|
|
294
|
+
returning the resolved source path across user library, user cache and
|
|
295
|
+
system library is the missing piece, and is worth having on its own.
|
|
296
|
+
|
|
297
|
+
- **No seed control anywhere, so a build cannot be reproduced.** Three
|
|
298
|
+
independent sources of randomness are all unseeded: `random.sample` for
|
|
299
|
+
conformer selection (`core/runtime.py`), `np.random.random()` for the
|
|
300
|
+
per-bond probability test (`cure/curecontroller.py`), and every `.mdp`
|
|
301
|
+
sets `gen-vel = yes` without `gen-seed`, so Gromacs picks a pseudo-random
|
|
302
|
+
one per run. Two runs of one config therefore diverge — example 6 gave 57
|
|
303
|
+
vs 60 incomplete triazines on two machines at the same 0.90 conversion.
|
|
304
|
+
That is convenient in one direction (independent replicas of a
|
|
305
|
+
quenched-disorder ensemble come free by re-running) but it means a build
|
|
306
|
+
reported in a paper cannot be reproduced exactly, and a failure seen once
|
|
307
|
+
may not reappear. The fix is a top-level `seed:` that feeds all three:
|
|
308
|
+
seed `random` and `np.random` at startup and write `gen-seed` into every
|
|
309
|
+
generated mdp, with replicas then requested by varying it rather than by
|
|
310
|
+
relying on entropy.
|
|
311
|
+
- **Drop the pre-3.5 matplotlib fallback** in `analysis/plot.py`'s
|
|
312
|
+
`_get_cmap()` once `matplotlib>=3.6` is a safe floor; the
|
|
313
|
+
`matplotlib.colormaps` registry is then always present.
|
|
314
|
+
|
|
315
|
+
## Example depot
|
|
316
|
+
|
|
317
|
+
- **Example 6's postcure anneal peaks too close to *T*:sub:`g` to relax the
|
|
318
|
+
network, and the fix is not simply "run it longer".** Measured on four
|
|
319
|
+
independent BPA builds: the postcure NPT plateau gives 1.1712 ± 0.0029
|
|
320
|
+
g/cm³ where the same systems melted and slowly re-cooled give 1.1983 ±
|
|
321
|
+
0.0037 g/cm³ -- 2.31% apart, with the plateau 2.6-2.8% below experiment
|
|
322
|
+
and the re-cooled value within 1%. The plateau is an under-relaxed
|
|
323
|
+
structure.
|
|
324
|
+
|
|
325
|
+
The mechanism, and the reason the obvious fix is the wrong one: the
|
|
326
|
+
example anneals at a 500 K peak, and the measured *T*:sub:`g` for this
|
|
327
|
+
system is 487.9 K. That is 12.1 K above the glass transition, for 80 ps.
|
|
328
|
+
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 only regime
|
|
330
|
+
where a crosslinked network moves at all. Lengthening an anneal that sits
|
|
331
|
+
12 K above *T*:sub:`g` extends a process that barely moves anything, so
|
|
332
|
+
the lever is the peak temperature, not the duration.
|
|
333
|
+
|
|
334
|
+
**Untested.** Nobody has yet built with a hotter anneal and compared it
|
|
335
|
+
against the melt-and-recool value, which is the experiment that would
|
|
336
|
+
settle it; the argument above is mechanism, not measurement. That is why
|
|
337
|
+
the example is documented rather than changed. Raising the peak also costs
|
|
338
|
+
wall-clock in a tutorial that should stay small, so the test needs to
|
|
339
|
+
report both whether it works and what it costs.
|
|
340
|
+
|
|
341
|
+
The general problem is worth more than the instance: **any protocol whose
|
|
342
|
+
relaxation depends on being above *T*:sub:`g` is fragile when *T*:sub:`g`
|
|
343
|
+
is unknown at configuration time**, which it always is -- you cannot know
|
|
344
|
+
it before building the thing. A fixed absolute peak temperature is a guess
|
|
345
|
+
that happens to be right or wrong per chemistry, silently. Something
|
|
346
|
+
expressed relative to an estimated or measured *T*:sub:`g`, or a postcure
|
|
347
|
+
that measures *T*:sub:`g` and then anneals accordingly, would be robust
|
|
348
|
+
where an absolute number is not. That is a real design change, not a
|
|
349
|
+
config edit.
|
|
350
|
+
|
|
351
|
+
Raised by the calibration study, which had already published the
|
|
352
|
+
pessimistic density before catching it -- the failure mode is reporting a
|
|
353
|
+
protocol artifact as a force-field result.
|
|
354
|
+
|
|
355
|
+
- **Example 5 is still not laptop-scale.** The `68d81fb` retune cut the
|
|
356
|
+
monomer pool to make HTPB/IPDI "fit in a reasonable wall time on a
|
|
357
|
+
laptop", but a validation run on 16 CPU cores took **10h17m** — about
|
|
358
|
+
ten times any other example (the next longest, PACM/DGEBA, was 2h15m).
|
|
359
|
+
The cost is structural: densification starts at 10 kg/m³ in a 27 nm box
|
|
360
|
+
and needs all 50 NPT repeats to compress geometrically (a steady 2.9%
|
|
361
|
+
box-side reduction per repeat) up to ~860 kg/m³, and the cure stage then
|
|
362
|
+
does drag/relax on long chains. Worth revisiting whether the low
|
|
363
|
+
starting density is really necessary, or whether the example can start
|
|
364
|
+
denser with a shorter densification.
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
- **More cyanate-ester variants.** Example 6 covers bisphenol-A
|
|
368
|
+
dicyanate. The same reaction and repair machinery carries over to other
|
|
369
|
+
bisphenol bridges with only a SMILES swap in `constituents` — bisphenol
|
|
370
|
+
F (methylene), bisphenol E (methylethylidene), hexafluorobisphenol A,
|
|
371
|
+
thioether, sulfone, dicyclopentadiene. A homologous series would
|
|
372
|
+
exercise the repair stage across chemistries and give the tutorials a
|
|
373
|
+
structure-property story.
|