htpolynet 2.3.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.0 → htpolynet-2.3.1}/CHANGELOG.md +57 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/PKG-INFO +1 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/ROADMAP.md +118 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/postsim.rst +16 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-run.rst +9 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/usage.rst +9 -4
- {htpolynet-2.3.0 → htpolynet-2.3.1}/pyproject.toml +1 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/analysis/analyze.py +1 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/analysis/postsim.py +1 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cli.py +1 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/projectfilesystem.py +25 -1
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/runtime.py +19 -8
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/software.py +18 -2
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_paramcache.py +20 -4
- {htpolynet-2.3.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.3.0 → htpolynet-2.3.1}/.claude/settings.json +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.claude/skills/htpolynet/SKILL.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.envrc +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.github/workflows/conda-forge-sync.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.github/workflows/docker.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.github/workflows/release.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.github/workflows/test.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.gitignore +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/.readthedocs.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/CITATION.cff +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/CLAUDE.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/LICENSE +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/MANIFEST.in +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docker/Dockerfile +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docker/compose.yml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docker/docker-entrypoint.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/Makefile +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/README.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/make.bat +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/requirements.txt +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/_static/.gitkeep +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/changelog.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/conf.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/monomer.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/0-liquid-styrene/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/monomer.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/STYCC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/final-box.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/sty-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/pics/styrene-polymerization.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/1-polystyrene/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/BPA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/GMA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/HIE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/four_dimers.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/gma-sty-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/p1-traces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/pics/vesys.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/2-bisgma-styrene-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-epoxy.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/DGE-labelled.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-2d.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/PAC-labelled.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dge-pac-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/dgesys.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/equil-rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/postsim-typical.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-e.png +0 -0
- {htpolynet-2.3.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.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/prod-tg.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r1.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r2.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/r3.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/rho_v_ns.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-e.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/pics/short-tg.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/3-pacm-dgeba-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/dfa-fde-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/4-dfda-fde-epoxy-thermoset/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/htpb-ipdi-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/5-htpb-ipdi/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/configuration.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/introduction.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/monomers.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-coloring.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-cured.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-detail.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/badcy-liq.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/buildtraces.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/cure_info.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/densification-density.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/pics/reaction_network.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/reactions.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/results.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/6-cyanate-ester/run.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/example-tutorials/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/htpolynetpackage.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/install.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/references/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/references/mol2-reference.pdf +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/references.bib +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/release-history.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/CURE.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/bond_filter.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/building-a-system.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-analyze.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/configs/configs-for-postsim.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/configuration-files.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/container-usage.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/flow1yaml.odg +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.eps +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/hydrogenated.fig +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/index.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/molecular-structure-inputs.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/STYCC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/TypicalUsageFlow.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/bond_filter.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-emb.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/chemdoodle-2dsketcher-styrene.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/hydrogenated.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_cases.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/pics/ring_pierce/ring_pierce_linkcell.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/postcure-repair.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/docs/source/user-guide/program-flow.rst +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/check-conda-sync.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/release.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/render-detail.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/render-detail.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/render-snapshot.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/scripts/run_all_examples.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/analysis/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/analysis/plot.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/analysis/utils.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/bondtemplate.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/configuration.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/coordinates.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/molecule.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/paramcache.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/topocoord.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/core/topology.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cure/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cure/chain.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cure/curecontroller.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cure/expandreactions.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/cure/reaction.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/ambertools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/command.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/gromacs.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/slurm.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/external/smiles_input.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/bondlist.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/lattice.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/linkcell.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/matrix4.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/geometry/ring.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/io/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/io/gro.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/io/mol2.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/io/pdb.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/repair/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/repair/cyanate_cap.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/repair/topology_surgery.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/0-liquid-styrene.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/1-polystyrene.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/2-bisgma-styrene-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/3-pacm-dgeba-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/4-dfda-fde-epoxy-thermoset.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/5-htpb-ipdi.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/example_depot/6-cyanate-ester.yaml +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/README.md +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/drag-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-npt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/relax-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-min.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/mdp/single-molecule-nvt.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DFA.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/FDE.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/inputs/STY.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/make-monomers.sh +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DFA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/DGE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/EMB.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/FDE.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/GMA.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/PAC.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/pics/STY.png +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DFA.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/DGE.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/EMB.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/FDE.pdb +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/GMA.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/PAC.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/molecules/sample-inputs/STY.mol2 +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readbonds.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/readgrx.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/resources/tcl/render.tcl +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/banner.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/checkpoint.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/dataframetools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/inputcheck.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/logsetup.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/profiling.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/stringthings.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/src/htpolynet/utils/vmd_viz.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/conftest.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/__init__.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.gro +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/config1.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.gro +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/config2.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/items31.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/items43.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/items45.edr +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/fixtures/short.mdp +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_bondtemplate.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_chain.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_configuration.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_dataframetools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_gpu_usability.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_get_energy_menu.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_gromacs_gmx_energy_trace.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_inputcheck.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_linkcell_pierce.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_paramcache_ambertools.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_parameterize_react.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_plot_smoke.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_resources.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_ring.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_ring_pierce_figs.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_slurm_script.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_smiles_input.py +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_topology/test.top +0 -0
- {htpolynet-2.3.0 → htpolynet-2.3.1}/tests/unit/test_topology.py +0 -0
|
@@ -7,6 +7,63 @@ 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
|
+
|
|
10
67
|
## [2.3.0] - 2026-08-23
|
|
11
68
|
|
|
12
69
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: htpolynet
|
|
3
|
-
Version: 2.3.
|
|
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/
|
|
@@ -27,6 +27,36 @@ 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 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.
|
|
30
60
|
- **Retire `ghcr.io/abramsgroup/htpolynet`.** Superseded by the
|
|
31
61
|
`cameronabrams` package; still public and still serving a June image to
|
|
32
62
|
anyone with an old link.
|
|
@@ -122,6 +152,56 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
122
152
|
cyanate-ester bridge series meant doing (a) and (b) by hand in a throwaway
|
|
123
153
|
RDKit script, which is exactly the work a user should not have to
|
|
124
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
|
+
|
|
125
205
|
- **`-lib` is read-only, and nothing says so.** `pfs.checkout()` and
|
|
126
206
|
`pfs.exists()` consult the `-lib` user library first, then the user cache,
|
|
127
207
|
then the system library -- but `pfs.checkin()` writes unconditionally to the
|
|
@@ -234,6 +314,44 @@ Coverage as of the last measurement: **38.8%** overall.
|
|
|
234
314
|
|
|
235
315
|
## Example depot
|
|
236
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
|
+
|
|
237
355
|
- **Example 5 is still not laptop-scale.** The `68d81fb` retune cut the
|
|
238
356
|
monomer pool to make HTPB/IPDI "fit in a reasonable wall time on a
|
|
239
357
|
laptop", but a validation run on 16 CPU cores took **10h17m** — about
|
{htpolynet-2.3.0 → htpolynet-2.3.1}/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``
|
|
@@ -222,8 +222,9 @@ checked in under the same name.
|
|
|
222
222
|
.. note::
|
|
223
223
|
|
|
224
224
|
A parameterization checked in before htpolynet 2.3 carries no record.
|
|
225
|
-
Those entries are still used
|
|
226
|
-
|
|
225
|
+
Those entries are still used **as-is**, so an existing cache keeps
|
|
226
|
+
working — but the build takes whatever charges they hold, which may not
|
|
227
|
+
be what your ``charge_method`` asks for. Each one logs a warning, and
|
|
227
228
|
the parameterization stage ends with a block listing them all. Rebuild
|
|
228
229
|
them with ``--force-parameterization`` if you need certainty about what
|
|
229
230
|
a build used.
|
|
@@ -387,7 +388,9 @@ The purpose of the ``postsim`` subcommand is to control the execution of several
|
|
|
387
388
|
-h, --help show this help message and exit
|
|
388
389
|
-proj PROJ [PROJ ...]
|
|
389
390
|
name of project directory
|
|
390
|
-
-lib LIB local user library of molecular structures and
|
|
391
|
+
-lib LIB local user library of molecular structures and
|
|
392
|
+
parameterizations (default: ./lib if it exists,
|
|
393
|
+
otherwise none)
|
|
391
394
|
-ocfg OCFG original htpolynet config file used to generate project(s)
|
|
392
395
|
-cfg CFG config file specifying the operations to perform
|
|
393
396
|
--no-banner suppress the startup banner
|
|
@@ -410,7 +413,9 @@ The ``analyze`` subcommand provides a shortcut interfaces to selected ``gmx``-st
|
|
|
410
413
|
-h, --help show this help message and exit
|
|
411
414
|
-proj PROJ [PROJ ...]
|
|
412
415
|
name of project directory
|
|
413
|
-
-lib LIB local user library of molecular structures and
|
|
416
|
+
-lib LIB local user library of molecular structures and
|
|
417
|
+
parameterizations (default: ./lib if it exists,
|
|
418
|
+
otherwise none)
|
|
414
419
|
-ocfg OCFG original htpolynet config file used to generate project(s)
|
|
415
420
|
-cfg CFG config file specifying the operations to perform
|
|
416
421
|
--no-banner suppress the startup banner
|
|
@@ -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)
|
|
@@ -235,7 +235,7 @@ def _add_gen_slurm_args(p):
|
|
|
235
235
|
def _add_analysis_args(p):
|
|
236
236
|
"""Adds the common arguments shared by the postsim and analyze subcommands."""
|
|
237
237
|
p.add_argument('-proj',type=str,default='',nargs='+',help='name of project directory')
|
|
238
|
-
p.add_argument('-lib',type=str,default=
|
|
238
|
+
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
239
|
p.add_argument('-ocfg',type=str,default='',help='original htpolynet config file used to generate project(s)')
|
|
240
240
|
p.add_argument('-cfg',type=str,default='',help='config file specifying the operations to perform')
|
|
241
241
|
p.add_argument('--no-banner',default=False,action='store_true',help='suppress the startup banner')
|
|
@@ -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
|
|
|
@@ -619,18 +619,27 @@ class Runtime:
|
|
|
619
619
|
of the stage is what someone scanning the tail of a log actually hits,
|
|
620
620
|
and it arrives while the expensive part of the build is still ahead of
|
|
621
621
|
them rather than behind.
|
|
622
|
+
|
|
623
|
+
Both messages have to say that the cached parameters are being *used*,
|
|
624
|
+
not merely that they could not be checked. A reader who upgrades with
|
|
625
|
+
an existing library, asks for one charge method, and gets another one's
|
|
626
|
+
numbers will otherwise conclude the cache guard does not work -- the
|
|
627
|
+
correct behavior here is indistinguishable from the bug it replaced
|
|
628
|
+
unless the message says which is happening.
|
|
622
629
|
"""
|
|
623
630
|
if not self.unverified_parameterizations:
|
|
624
631
|
return
|
|
625
632
|
names = sorted(set(self.unverified_parameterizations))
|
|
626
633
|
ess = '' if len(names) == 1 else 's'
|
|
627
634
|
requested = paramcache.build_key(self.cfg.ambertools)
|
|
628
|
-
my_logger(f'{len(names)} parameterization{ess}
|
|
629
|
-
logger.warning(
|
|
630
|
-
logger.warning(
|
|
631
|
-
logger.warning(f'
|
|
635
|
+
my_logger(f'{len(names)} parameterization{ess} reused without provenance', logger.warning)
|
|
636
|
+
logger.warning('These were taken from the library, which records nothing about how they were')
|
|
637
|
+
logger.warning('built. This build therefore carries whatever charges those entries hold, and')
|
|
638
|
+
logger.warning(f'they may not be {requested["charge_method"]!r}:')
|
|
632
639
|
my_logger(names, logger.warning)
|
|
633
|
-
logger.warning('
|
|
640
|
+
logger.warning('This is expected for entries written before htpolynet 2.3, and is not a')
|
|
641
|
+
logger.warning('failure. Rebuild them with --force-parameterization if this build\'s charges')
|
|
642
|
+
logger.warning('need to be certain.')
|
|
634
643
|
|
|
635
644
|
@staticmethod
|
|
636
645
|
def _checkin_parameterization(mname, overwrite):
|
|
@@ -687,9 +696,11 @@ class Runtime:
|
|
|
687
696
|
pfs.checkout(keyfile)
|
|
688
697
|
stored = paramcache.read_key(M.name)
|
|
689
698
|
if stored is None:
|
|
690
|
-
logger.warning(f'
|
|
691
|
-
f'
|
|
692
|
-
f'
|
|
699
|
+
logger.warning(f'Reusing cached parameterization for {M.name}, which carries no record of '
|
|
700
|
+
f'how it was built: this build takes whatever charges that entry holds, and '
|
|
701
|
+
f'they may not be {requested["charge_method"]!r}. Expected for an entry '
|
|
702
|
+
f'written before htpolynet 2.3; rebuild it with --force-parameterization '
|
|
703
|
+
f'if this build\'s charges need to be certain.')
|
|
693
704
|
self.unverified_parameterizations.append(M.name)
|
|
694
705
|
return []
|
|
695
706
|
diffs = paramcache.describe_mismatch(stored, requested)
|
|
@@ -90,8 +90,15 @@ def _mdrun_cmd(base):
|
|
|
90
90
|
|
|
91
91
|
def _get_git_commit():
|
|
92
92
|
"""Records the short git commit hash of the htpolynet source tree and
|
|
93
|
-
whether there are uncommitted changes.
|
|
94
|
-
|
|
93
|
+
whether there are uncommitted changes.
|
|
94
|
+
|
|
95
|
+
An installed copy -- pip, conda, or the published container -- has no
|
|
96
|
+
``.git`` beside it, so the git lookup fails and there is nothing to
|
|
97
|
+
report. Reporting 'unknown' there leaves a build with no way to answer
|
|
98
|
+
"what code produced this" from inside itself, which is exactly the
|
|
99
|
+
question the parameterization records exist to answer for molecules.
|
|
100
|
+
Fall back to the installed distribution version, which for a released
|
|
101
|
+
install maps to a tag and is the honest answer.
|
|
95
102
|
"""
|
|
96
103
|
global git_commit
|
|
97
104
|
src = os.path.dirname(__file__)
|
|
@@ -108,6 +115,15 @@ def _get_git_commit():
|
|
|
108
115
|
)
|
|
109
116
|
if dirty.returncode == 0 and dirty.stdout.strip():
|
|
110
117
|
git_commit += ' (uncommitted changes present)'
|
|
118
|
+
return
|
|
119
|
+
except Exception:
|
|
120
|
+
pass
|
|
121
|
+
try:
|
|
122
|
+
from importlib.metadata import version, PackageNotFoundError
|
|
123
|
+
try:
|
|
124
|
+
git_commit = f'not a git checkout (installed version {version("htpolynet")})'
|
|
125
|
+
except PackageNotFoundError:
|
|
126
|
+
pass
|
|
111
127
|
except Exception:
|
|
112
128
|
pass
|
|
113
129
|
|
|
@@ -181,6 +181,11 @@ class TestCachedParameterizationMismatch:
|
|
|
181
181
|
assert diffs == []
|
|
182
182
|
assert 'TAZ' in caplog.text
|
|
183
183
|
assert 'force-parameterization' in caplog.text
|
|
184
|
+
# The message must say the cached values are being USED, not merely
|
|
185
|
+
# that they could not be checked: correct behavior here is otherwise
|
|
186
|
+
# indistinguishable from the bug it replaced.
|
|
187
|
+
assert 'Reusing cached parameterization' in caplog.text
|
|
188
|
+
assert 'may not be' in caplog.text
|
|
184
189
|
assert runtime.unverified_parameterizations == ['TAZ'], \
|
|
185
190
|
'an unverifiable entry must also reach the stage-end summary'
|
|
186
191
|
|
|
@@ -212,7 +217,7 @@ class TestCachedParameterizationMismatch:
|
|
|
212
217
|
paramcache.write_key('TAZ', paramcache.build_key({'charge_method': 'bcc'}))
|
|
213
218
|
with caplog.at_level('WARNING'):
|
|
214
219
|
assert _mismatch('TAZ', charge_method='bcc') == []
|
|
215
|
-
assert 'no record of how it was built' in caplog.text
|
|
220
|
+
assert 'carries no record of how it was built' in caplog.text
|
|
216
221
|
|
|
217
222
|
|
|
218
223
|
class TestCheckinParameterization:
|
|
@@ -311,16 +316,27 @@ class TestUnverifiedSummary:
|
|
|
311
316
|
|
|
312
317
|
def test_states_the_count_and_the_requested_charge_method(self, caplog):
|
|
313
318
|
text = self._report(['TAZ', 'BAF'], caplog, charge_method='bcc')
|
|
314
|
-
assert '2 parameterizations
|
|
319
|
+
assert '2 parameterizations reused without provenance' in text
|
|
315
320
|
assert "'bcc'" in text
|
|
316
321
|
|
|
317
322
|
def test_singular_for_one_molecule(self, caplog):
|
|
318
323
|
text = self._report(['TAZ'], caplog, charge_method='bcc')
|
|
319
|
-
assert '1 parameterization
|
|
324
|
+
assert '1 parameterization reused without provenance' in text
|
|
325
|
+
|
|
326
|
+
def test_says_the_build_carries_the_cached_charges(self, caplog):
|
|
327
|
+
# Without this, a reader who upgrades with an existing library, asks
|
|
328
|
+
# for bcc and gets gas numbers concludes the guard is broken.
|
|
329
|
+
text = self._report(['TAZ'], caplog, charge_method='bcc')
|
|
330
|
+
assert 'carries whatever charges those entries hold' in text
|
|
331
|
+
assert 'may not be' in text
|
|
332
|
+
|
|
333
|
+
def test_says_this_is_expected_rather_than_a_failure(self, caplog):
|
|
334
|
+
text = self._report(['TAZ'], caplog, charge_method='bcc')
|
|
335
|
+
assert 'is not a' in text and 'failure' in text
|
|
320
336
|
|
|
321
337
|
def test_says_how_to_resolve_it(self, caplog):
|
|
322
338
|
assert 'force-parameterization' in self._report(['TAZ'], caplog, charge_method='bcc')
|
|
323
339
|
|
|
324
340
|
def test_a_molecule_reported_twice_is_listed_once(self, caplog):
|
|
325
341
|
text = self._report(['TAZ', 'TAZ'], caplog, charge_method='bcc')
|
|
326
|
-
assert '1 parameterization
|
|
342
|
+
assert '1 parameterization reused without provenance' in text
|
|
@@ -476,3 +476,54 @@ class TestDirsIntegration(unittest.TestCase):
|
|
|
476
476
|
proj_path = os.path.join(self.base, 'p')
|
|
477
477
|
for d in Dirs.analyze_topdirs:
|
|
478
478
|
self.assertTrue(os.path.isdir(os.path.join(proj_path, d)))
|
|
479
|
+
|
|
480
|
+
|
|
481
|
+
class TestResolveUserLibrary(unittest.TestCase):
|
|
482
|
+
"""`htpolynet postsim` used to die in any directory without a `lib/`.
|
|
483
|
+
|
|
484
|
+
`-lib` defaulted to the string 'lib' for postsim and analyze, but only
|
|
485
|
+
`run` creates that tree, so the default value of a flag the user never
|
|
486
|
+
typed reached UserLibrary and tripped its existence assertion. The
|
|
487
|
+
documented container invocation -- postsim against a staged directory
|
|
488
|
+
holding only finished results -- failed in three seconds.
|
|
489
|
+
"""
|
|
490
|
+
|
|
491
|
+
def setUp(self):
|
|
492
|
+
self.tmpdir = tempfile.mkdtemp()
|
|
493
|
+
self.orig = os.getcwd()
|
|
494
|
+
os.chdir(self.tmpdir)
|
|
495
|
+
|
|
496
|
+
def tearDown(self):
|
|
497
|
+
os.chdir(self.orig)
|
|
498
|
+
shutil.rmtree(self.tmpdir, ignore_errors=True)
|
|
499
|
+
|
|
500
|
+
def test_absent_default_resolves_to_no_library(self):
|
|
501
|
+
self.assertIsNone(pfs.resolve_user_library(None))
|
|
502
|
+
|
|
503
|
+
def test_present_default_is_used(self):
|
|
504
|
+
os.makedirs('lib')
|
|
505
|
+
self.assertEqual(pfs.resolve_user_library(None), 'lib')
|
|
506
|
+
|
|
507
|
+
def test_explicit_path_is_returned_even_when_missing(self):
|
|
508
|
+
# A typo'd -lib must fail loudly in UserLibrary rather than silently
|
|
509
|
+
# degrade to no library.
|
|
510
|
+
self.assertEqual(pfs.resolve_user_library('mylib'), 'mylib')
|
|
511
|
+
|
|
512
|
+
def test_explicit_path_still_reaches_the_existence_check(self):
|
|
513
|
+
with self.assertRaises(AssertionError):
|
|
514
|
+
UserLibrary(pfs.resolve_user_library('/this/path/does/not/exist'))
|
|
515
|
+
|
|
516
|
+
def test_resolved_absent_default_never_reaches_the_check(self):
|
|
517
|
+
# The regression itself: with no lib/ present and no -lib given,
|
|
518
|
+
# nothing is constructed, so nothing can assert.
|
|
519
|
+
resolved = pfs.resolve_user_library(None)
|
|
520
|
+
self.assertIsNone(resolved)
|
|
521
|
+
pfs_obj = ProjectFileSystem(root=self.tmpdir, userlibrary=resolved, mock=True)
|
|
522
|
+
self.assertIsNone(pfs_obj.userlibrary)
|
|
523
|
+
|
|
524
|
+
def test_error_message_names_the_flag_and_the_remedy(self):
|
|
525
|
+
with self.assertRaises(AssertionError) as cm:
|
|
526
|
+
UserLibrary('/this/path/does/not/exist')
|
|
527
|
+
msg = str(cm.exception)
|
|
528
|
+
self.assertIn('-lib', msg)
|
|
529
|
+
self.assertIn('/this/path/does/not/exist', msg)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Tests what an htpolynet build can say about the code that produced it.
|
|
2
|
+
|
|
3
|
+
`htpolynet info` reports a git commit, which works from a source checkout and
|
|
4
|
+
does not exist for an installed copy -- pip, conda, or the published
|
|
5
|
+
container, none of which carry a `.git`. Reporting 'unknown' there leaves a
|
|
6
|
+
build unable to answer "what code produced this" from inside itself, which is
|
|
7
|
+
the same question the parameterization records answer for molecules.
|
|
8
|
+
|
|
9
|
+
Author: Cameron F. Abrams <cfa22@drexel.edu>
|
|
10
|
+
"""
|
|
11
|
+
import subprocess
|
|
12
|
+
|
|
13
|
+
import pytest
|
|
14
|
+
|
|
15
|
+
import htpolynet.external.software as software
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.fixture(autouse=True)
|
|
19
|
+
def restore_git_commit():
|
|
20
|
+
"""software.git_commit is module state; put it back afterwards."""
|
|
21
|
+
original = software.git_commit
|
|
22
|
+
yield
|
|
23
|
+
software.git_commit = original
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def _no_git(monkeypatch):
|
|
27
|
+
"""Makes the git lookup fail the way it does outside a checkout."""
|
|
28
|
+
def boom(*a, **kw):
|
|
29
|
+
raise FileNotFoundError('git')
|
|
30
|
+
monkeypatch.setattr(subprocess, 'run', boom)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestGitCommitReporting:
|
|
34
|
+
|
|
35
|
+
def test_a_checkout_reports_a_commit(self):
|
|
36
|
+
software.git_commit = 'unset'
|
|
37
|
+
software._get_git_commit()
|
|
38
|
+
# The test suite runs inside the repo, so this is a real lookup.
|
|
39
|
+
assert software.git_commit != 'unset'
|
|
40
|
+
assert 'unknown' not in software.git_commit
|
|
41
|
+
|
|
42
|
+
def test_an_installed_copy_reports_its_version(self, monkeypatch):
|
|
43
|
+
_no_git(monkeypatch)
|
|
44
|
+
software.git_commit = 'unset'
|
|
45
|
+
software._get_git_commit()
|
|
46
|
+
assert 'installed version' in software.git_commit
|
|
47
|
+
assert 'not a git checkout' in software.git_commit
|
|
48
|
+
|
|
49
|
+
def test_an_installed_copy_never_reports_unknown(self, monkeypatch):
|
|
50
|
+
# The container case 8a hit: htpolynet info said 'unknown', so a build
|
|
51
|
+
# could not identify its own code.
|
|
52
|
+
_no_git(monkeypatch)
|
|
53
|
+
software.git_commit = 'unknown'
|
|
54
|
+
software._get_git_commit()
|
|
55
|
+
assert software.git_commit != 'unknown'
|
|
56
|
+
|
|
57
|
+
def test_the_lookup_never_raises(self, monkeypatch):
|
|
58
|
+
# Provenance reporting must not be able to abort a build.
|
|
59
|
+
_no_git(monkeypatch)
|
|
60
|
+
monkeypatch.setattr(software, '__name__', software.__name__)
|
|
61
|
+
software._get_git_commit()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|