mdinterface 1.5.3__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. mdinterface-2.0.0/CHANGELOG.md +177 -0
  2. mdinterface-2.0.0/CONTRIBUTING.md +67 -0
  3. {mdinterface-1.5.3 → mdinterface-2.0.0}/MANIFEST.in +10 -4
  4. {mdinterface-1.5.3/mdinterface.egg-info → mdinterface-2.0.0}/PKG-INFO +71 -16
  5. {mdinterface-1.5.3 → mdinterface-2.0.0}/README.md +62 -12
  6. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/externals.md +4 -0
  7. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/io.md +4 -0
  8. mdinterface-2.0.0/docs/development/releasing.md +57 -0
  9. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/guide/database.md +4 -2
  10. mdinterface-2.0.0/docs/guide/migration-2.md +77 -0
  11. mdinterface-2.0.0/docs/guide/polymer.md +179 -0
  12. mdinterface-2.0.0/docs/guide/simcell.md +287 -0
  13. mdinterface-2.0.0/docs/guide/specie.md +119 -0
  14. mdinterface-2.0.0/docs/installation.md +111 -0
  15. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/quickstart.md +1 -1
  16. mdinterface-2.0.0/environment-full.yml +23 -0
  17. mdinterface-2.0.0/examples/data/membrane.data.lammps +28832 -0
  18. mdinterface-2.0.0/examples/data/membrane.production.dump +9066 -0
  19. mdinterface-2.0.0/examples/data/water_frame.dump +12 -0
  20. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/electrode_interface.py +1 -2
  21. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/multilayer.py +1 -3
  22. mdinterface-2.0.0/examples/polymer/data/mon1/monomer_1.lammps.lmp +884 -0
  23. mdinterface-2.0.0/examples/polymer/data/mon2/monomer_2.lammps.lmp +764 -0
  24. mdinterface-2.0.0/examples/polymer/polymer_from_smiles.py +25 -0
  25. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/polymer/polymer_piperion.py +20 -37
  26. mdinterface-2.0.0/examples/smiles_box.py +10 -0
  27. mdinterface-2.0.0/examples/solvent_pocket.py +45 -0
  28. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/__init__.py +12 -8
  29. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/build/__init__.py +2 -2
  30. mdinterface-2.0.0/mdinterface/build/box.py +334 -0
  31. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/build/builder.py +177 -120
  32. mdinterface-2.0.0/mdinterface/build/compartment.py +106 -0
  33. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/build/polymerize.py +62 -11
  34. mdinterface-2.0.0/mdinterface/build/regions.py +260 -0
  35. mdinterface-2.0.0/mdinterface/build/snippets.py +95 -0
  36. mdinterface-2.0.0/mdinterface/build/solvent.py +556 -0
  37. mdinterface-2.0.0/mdinterface/config.ini +13 -0
  38. mdinterface-2.0.0/mdinterface/config.py +34 -0
  39. mdinterface-2.0.0/mdinterface/core/chemistry.py +169 -0
  40. mdinterface-2.0.0/mdinterface/core/polymer.py +275 -0
  41. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/core/specie.py +405 -64
  42. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/core/topology.py +4 -4
  43. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/ions.py +4 -0
  44. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/molecules.py +2 -2
  45. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/__init__.py +7 -7
  46. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/ligpargen.py +218 -142
  47. mdinterface-2.0.0/mdinterface/externals/obabel.py +90 -0
  48. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/pyscf.py +2 -2
  49. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/io/__init__.py +1 -1
  50. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/io/lammpswriter.py +48 -16
  51. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/io/packmol.py +12 -4
  52. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/io/read.py +3 -0
  53. mdinterface-2.0.0/mdinterface/io/structure_metadata.py +60 -0
  54. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/map.py +0 -8
  55. {mdinterface-1.5.3 → mdinterface-2.0.0/mdinterface.egg-info}/PKG-INFO +71 -16
  56. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface.egg-info/SOURCES.txt +31 -6
  57. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface.egg-info/requires.txt +6 -0
  58. mdinterface-2.0.0/mdinterface.egg-info/top_level.txt +1 -0
  59. mdinterface-2.0.0/mkdocs.yml +72 -0
  60. {mdinterface-1.5.3 → mdinterface-2.0.0}/pyproject.toml +20 -5
  61. {mdinterface-1.5.3 → mdinterface-2.0.0}/requirements.txt +2 -1
  62. mdinterface-2.0.0/scripts/extract_changelog_summary.py +78 -0
  63. mdinterface-2.0.0/scripts/verify_distribution_contents.py +64 -0
  64. mdinterface-2.0.0/tests/test_box.py +219 -0
  65. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/test_builder.py +76 -22
  66. mdinterface-2.0.0/tests/test_changelog_summary.py +91 -0
  67. mdinterface-2.0.0/tests/test_chemistry.py +422 -0
  68. mdinterface-2.0.0/tests/test_compartment.py +85 -0
  69. mdinterface-2.0.0/tests/test_distribution_contents.py +79 -0
  70. mdinterface-2.0.0/tests/test_imports.py +75 -0
  71. mdinterface-2.0.0/tests/test_ligpargen.py +110 -0
  72. mdinterface-2.0.0/tests/test_parameterization.py +232 -0
  73. mdinterface-2.0.0/tests/test_regions.py +173 -0
  74. mdinterface-2.0.0/tests/test_solvent.py +467 -0
  75. mdinterface-2.0.0/tests/test_structure_metadata.py +155 -0
  76. mdinterface-1.5.3/docs/guide/polymer.md +0 -176
  77. mdinterface-1.5.3/docs/guide/simcell.md +0 -170
  78. mdinterface-1.5.3/docs/guide/specie.md +0 -60
  79. mdinterface-1.5.3/docs/installation.md +0 -86
  80. mdinterface-1.5.3/examples/legacy/make_POSCAR.py +0 -67
  81. mdinterface-1.5.3/examples/legacy/make_box.py +0 -76
  82. mdinterface-1.5.3/examples/legacy/make_polymer.py +0 -74
  83. mdinterface-1.5.3/examples/legacy/make_solvent_box.py +0 -67
  84. mdinterface-1.5.3/examples/legacy/make_specie_ligpargen_resp.py +0 -26
  85. mdinterface-1.5.3/mdinterface/build/box.py +0 -232
  86. mdinterface-1.5.3/mdinterface/build/snippets.py +0 -144
  87. mdinterface-1.5.3/mdinterface/build/solvent.py +0 -324
  88. mdinterface-1.5.3/mdinterface/config.py +0 -40
  89. mdinterface-1.5.3/mdinterface/core/polymer.py +0 -239
  90. mdinterface-1.5.3/mdinterface/externals/obabel.py +0 -53
  91. mdinterface-1.5.3/mdinterface/simulationbox.py +0 -581
  92. mdinterface-1.5.3/mdinterface.egg-info/top_level.txt +0 -6
  93. mdinterface-1.5.3/tests/test_solvent.py +0 -129
  94. {mdinterface-1.5.3 → mdinterface-2.0.0}/LICENSE +0 -0
  95. {mdinterface-1.5.3 → mdinterface-2.0.0}/assets/mdinterface.png +0 -0
  96. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/database.md +0 -0
  97. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/polymer.md +0 -0
  98. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/simcell.md +0 -0
  99. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/api/specie.md +0 -0
  100. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/assets/mdinterface.png +0 -0
  101. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/guide/logging.md +0 -0
  102. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/index.md +0 -0
  103. {mdinterface-1.5.3 → mdinterface-2.0.0}/docs/requirements.txt +0 -0
  104. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/multisolvent_box.py +0 -0
  105. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/sandwich_from_traj.py +0 -0
  106. {mdinterface-1.5.3 → mdinterface-2.0.0}/examples/solvent_box.py +0 -0
  107. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/build/continuum2sim.py +0 -0
  108. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/core/__init__.py +0 -0
  109. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/__init__.py +0 -0
  110. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/graphene.py +0 -0
  111. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/metals.py +0 -0
  112. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/database/nobles.py +0 -0
  113. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/aimd.py +0 -0
  114. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/ase.py +0 -0
  115. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/externals/optimization.py +0 -0
  116. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/io/gromacswriter.py +0 -0
  117. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/read/cp2ktraj.py +0 -0
  118. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/read/lammpstraj.py +0 -0
  119. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/read/read.py +0 -0
  120. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/read/trajectory.py +0 -0
  121. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/read/xyztraj.py +0 -0
  122. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/__init__.py +0 -0
  123. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/auxiliary.py +0 -0
  124. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/draw.py +0 -0
  125. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/graphs.py +0 -0
  126. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/logger.py +0 -0
  127. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/poisson.py +0 -0
  128. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/rings.py +0 -0
  129. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface/utils/units.py +0 -0
  130. {mdinterface-1.5.3 → mdinterface-2.0.0}/mdinterface.egg-info/dependency_links.txt +0 -0
  131. {mdinterface-1.5.3 → mdinterface-2.0.0}/setup.cfg +0 -0
  132. {mdinterface-1.5.3 → mdinterface-2.0.0}/setup.py +0 -0
  133. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/__init__.py +0 -0
  134. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/test_auxiliary.py +0 -0
  135. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/test_database.py +0 -0
  136. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/test_specie.py +0 -0
  137. {mdinterface-1.5.3 → mdinterface-2.0.0}/tests/test_topology.py +0 -0
@@ -0,0 +1,177 @@
1
+ # Changelog
2
+
3
+ All notable changes to mdinterface are documented here.
4
+
5
+ ## [Unreleased]
6
+
7
+ ## [2.0.0] - 2026-09-28
8
+
9
+ Makes `SimCell` the sole system builder, removing the deprecated `SimulationBox` and `BoxBuilder` APIs and adding spatially constrained solvent regions and optional LAMMPS structural metadata. This major release also changes explicit centering behavior, requires Python 3.10 or newer, and adds RDKit molecular preparation, atomic force-field parameterization, export validation, and improved external-tool diagnostics.
10
+
11
+ ### Added
12
+ - `Specie.parameterize()` applies complete LigParGen results atomically and returns a charge audit for direct or segmented parameterization.
13
+ - `Specie.mark_attachment_sites()` selects validated polymer leaving atoms using atom maps.
14
+ - `Specie.validate_force_field()` and coefficient-bearing LAMMPS exports check parameter completeness, with optional `expected_charge` validation at export.
15
+ - `Specie.generate_conformer()` and `minimize_geometry()`, inherited by `Polymer`, provide separate or combined RDKit embedding and MMFF94 minimization while preserving simulation parameters.
16
+ - A mapped-SMILES polymer example prepares and parameterizes a charged chain and exports it with counterions.
17
+ - `Specie(smiles=...)` and RDKit molecule inputs preserve chemical graphs, formal charges, stereochemistry, and atom maps, with `to_rdkit()` and `to_smiles()` conversion.
18
+ - `SimCell.write_lammps(metadata=...)` optionally exports versioned structural JSON with final atom/type IDs, species groups, connectivity, coefficients and a data-file checksum, without choosing simulation settings.
19
+ - `Sphere`, `Box`, and `Cylinder` regions for spatially constrained PACKMOL placement
20
+ - `Region.fill()` for assigning content to a region
21
+ - `SimCell.add_solvent(regions=...)` for spatially heterogeneous solvent layers
22
+ - Nested regions through `Region.fill(regions=...)`
23
+ - Reproducible automatic region placement through `center="random"` and `SimCell.add_solvent(seed=...)`
24
+
25
+ ### Changed
26
+ - `Polymer` inherits force-field parameters from `Specie` monomers with distinct labels per repeat unless explicit topology overrides are supplied.
27
+ - Large-molecule parameterization uses explicit charge-correction options and checks capped segment and expanded junction sizes before running LigParGen.
28
+ - `Polymer.refine_junctions(snippet_radius=..., charge_correction=..., cap_element=...)` replaces `refine_polymer_topology()` and returns a charge audit, with public `junction_bonds` for connectivity.
29
+ - The piperion example prepares geometry with RDKit and prints the refinement charge audit instead of recommending a neutral-charge ML relaxation for an ionic chain.
30
+ - RDKit is now a required core dependency for molecular graph handling and SMILES support.
31
+ - `Polymer` preserves explicit junction bonds and validates monomer chemistry instead of deriving junction connectivity from coordinates.
32
+ - RDKit-backed LigParGen inputs use MOL files, and installation instructions and the full environment pin the compatible fork to commit `ad78036` to preserve chemistry during atom reordering.
33
+ - `SimulationBox`, its module `mdinterface.simulationbox`, and the `BoxBuilder` alias are removed; migrate to `SimCell` using the 2.0 migration guide.
34
+ - Legacy examples are removed from the repository and source distribution; current examples use `SimCell` and `Polymer`.
35
+ - `SimCell.build(center=True)` now places the first layer at the box midpoint instead of across the periodic boundary; the default remains `False`.
36
+ - Minimum supported Python version is now 3.10
37
+ - Supported Python versions are now tested through Python 3.14
38
+ - PACKMOL is now installed automatically from its upstream PyPI package
39
+ - Importing `mdinterface` no longer loads optional AIMD and plotting dependencies or reads user configuration
40
+ - PACKMOL execution and output failures now raise `PackmolError` with retained diagnostic file locations instead of returning `None`
41
+ - LigParGen setup, execution, and output failures now raise `LigParGenError` with actionable installation or configuration guidance and retained diagnostic file locations
42
+ - `build.box.populate_box()` now accepts `Specie` objects and returns `ase.Atoms`
43
+ - PACKMOL templates now use ASE instead of MDAnalysis, eliminating PDB-completeness warnings for temporary files
44
+
45
+ ### Fixed
46
+ - Source distributions include the full parameterization environment and MkDocs configuration referenced by the bundled setup instructions.
47
+ - SMILES parsing preserves explicit hydrogen atom maps used to select polymer attachment sites.
48
+ - `Specie.repeat()` scales the stored molecular charge and preserves the original copy's atom maps.
49
+ - Junction refinement retains distinct improper assignments with identical coefficients.
50
+ - Database ions retain their formal molecular charge independently of scaled force-field partial charges.
51
+ - LAMMPS coefficient export uses unique temporary files instead of overwriting `tmp_data.lammps` in the working directory.
52
+ - Explicit zero-valued bonded parameters are retained instead of being discarded during type mapping.
53
+ - Imported LAMMPS bond connectivity survives trajectory coordinate updates, atom reordering, and `Specie.repeat()` without distance-based bond inference.
54
+ - Junction refinement leaves the original chain unchanged if any parameterization fails.
55
+ - Charge estimation uses the stored molecular charge, rejects conflicting overrides, and passes the charge through the Open Babel and RESP backends.
56
+ - `Specie(ligpargen=True)` now retains the partial charges returned by parameterization.
57
+ - Polymer refinement preserves charged groups, uses neutral snippet caps, and no longer reuses parameters based only on element strings.
58
+ - The piperion example locates its charged nitrogen correctly and validates charge neutrality after refinement.
59
+ - Nested regions now remain inside their parent's actual shape, including randomly placed regions.
60
+ - `Region.fill()` validates content parameters, and solvent mixtures reject ambiguous scalar counts without a mixing ratio instead of silently omitting species.
61
+ - Bulk solutes now exclude filled regions and use the remaining volume for concentration-based counts; incompatible fixed-center and concentration-profile placement raises an error.
62
+ - Water model documentation now describes `Water(model="ewald")` as modified TIP3P for Ewald electrostatics (its parameters were always TIP3P-Ewald, not SPC/E) and no longer swaps variable names in the database guide
63
+ - Slab tiling producing cells smaller than the requested XY dimensions when the nearest repeat count rounded down
64
+ - Spurious MDAnalysis topology-guessing warnings in `Specie.to_universe()` and `build.box.populate_box()`
65
+ - Missing `elements` topology data in universes created by `Specie.to_universe()`
66
+ - Region-constrained PACKMOL placements exceeding requested boundaries because of loose default solver precision
67
+ - Wheels including repository documentation, examples, tests, and local planning files because package discovery was not limited to `mdinterface`
68
+ - Missing `mdinterface/config.ini` in wheels, which broke the default configuration fallback after installation
69
+
70
+ ### Deprecated
71
+ - `add_solvent(solute_pos="left"/"right")` - pass an equivalent `Region`, such as `Box.from_bounds(...)`, instead
72
+
73
+ ---
74
+
75
+ ## [1.5.4] - 2026-08-12
76
+
77
+ Automates PyPI releases with a test gate and a required changelog summary, and fixes `SimulationBox` crashing on its most common usage (density-based single solvent) while making its deprecation warning actually visible.
78
+
79
+ ### Changed
80
+ - Release process: `publish.yml` replaced by `release.yml` - now runs the test suite and requires a changelog summary paragraph before publishing to PyPI, and creates a draft (not published) GitHub release with changelog-sourced notes instead of autogenerated commit notes
81
+ - `.github/workflows/release.yml` also accepts manual `workflow_dispatch` (with a `tag` input) for re-running a release without re-tagging
82
+
83
+ ### Added
84
+ - `.claude/skills/release` documenting the version-bump/changelog/tag procedure
85
+ - `scripts/extract_changelog_summary.py` for extracting a version's changelog summary paragraph
86
+
87
+ ### Deprecated
88
+ - `SimulationBox` now emits a `DeprecationWarning` on construction; use `SimCell` instead
89
+
90
+ ### Fixed
91
+ - `simulationbox.py` called `warnings.filterwarnings('ignore')` at import time, silently suppressing all warnings process-wide for the rest of the program (including the existing `BoxBuilder` deprecation warning and this module's own warnings) - removed
92
+ - `SimulationBox` crashed with `AttributeError: AtomGroup has no attribute get_masses` when using a single solvent with density (no `ratio`/`nsolvent`) - its most common usage
93
+
94
+ ---
95
+
96
+ ## [1.5.3] — 2026-07-09
97
+
98
+ ### Fixed
99
+ - `NameError` in `DATAWriter` when `convert_units=False` (`coordinates` and `triv` were only assigned inside the conditional branch)
100
+ - Improper type label in LAMMPS coefficient output was silently truncated to the first atom; now writes the full four-atom type string
101
+ - `NameError` in `Specie.estimate_charges(assign=True)` for non-RESP methods (`atoms` was only defined in the RESP branch)
102
+ - Wrong return-type annotation on `SimCell._stack_layers` (declared 2-tuple, returns 3-tuple)
103
+ - `map_impropers(None)` returned a 2-tuple instead of the consistent 3-tuple returned by all other `map_*` functions
104
+ - Dead unreachable error-checking code removed from `generate_missing_interactions`
105
+
106
+ ### Changed
107
+ - Canonical repository moved from GitLab to GitHub
108
+ - Deployment: tag/version consistency check and GitHub Release creation added to publish workflow
109
+ - Deployment: docs workflow now only rebuilds when source files change
110
+
111
+ ---
112
+
113
+ ## [1.5.2] — 2026-03-31
114
+
115
+ ### Fixed
116
+ - Topology label mismatch for large molecules in LigParGen segmentation
117
+
118
+ ---
119
+
120
+ ## [1.5.1] — 2026-03-31
121
+
122
+ ### Added
123
+ - GitHub Actions workflow for automated PyPI publishing on version tags
124
+ - GROMACS output: `write_gromacs_itp`, `write_gromacs_top`, `Specie.write_gro()`
125
+ - `refine_large_specie_topology` for LigParGen parameterisation of molecules with more than 200 atoms
126
+ - `Specie.write_gro()` for writing GROMACS structure files
127
+ - `BOSSdir` config key supporting local install, container, and direct-path modes
128
+
129
+ ### Fixed
130
+ - Junction LJ type correction in segment and polymer refinement
131
+ - Docs CI: use `--no-deps` to avoid building compiled dependencies (libarvo)
132
+ - PACKMOL and LigParGen now use a temp directory; kept on failure for inspection
133
+
134
+ ### Changed
135
+ - `libarvo` made optional; only required for volume/radius estimation
136
+ - Logging style updated throughout; improved SimCell and externals API docs
137
+
138
+ ---
139
+
140
+ ## [1.5.0] — 2026-02-01
141
+
142
+ ### Added
143
+ - MkDocs documentation site with Material theme
144
+ - Polymer guide and reorganised examples
145
+ - `SimCell` fluent builder API (replaces `BoxBuilder`)
146
+ - Multi-solvent support with `ratio` and mixed `nsolvent` lists
147
+ - `solvent.py` extracted from `build.py` for clarity
148
+ - `dilate` and `packmol_tolerance` parameters on `add_solvent`
149
+ - `hijack`, `stack_axis`, `match_cell` options on `SimCell.build()`
150
+ - Logging infrastructure with `set_verbosity` and structured headers
151
+
152
+ ### Changed
153
+ - `ions`/`nions` renamed to `solute`/`nsolute` throughout
154
+ - `populate_with_ions` renamed to `populate_solutes`
155
+ - `BoxBuilder` retained as a deprecated alias for `SimCell`
156
+ - Examples reorganised into `simulation_box/` and `box_builder/` subfolders
157
+
158
+ ### Fixed
159
+ - Duplicate log output caused by missing `propagate=False`
160
+ - Mutable default arguments in several functions
161
+
162
+ ---
163
+
164
+ ## [1.4.0]
165
+
166
+ ### Added
167
+ - Initial `BoxBuilder` fluent API for multi-layer simulation box assembly
168
+ - `to_ase()` output method
169
+ - Noble gases in database
170
+
171
+ ### Fixed
172
+ - Shell injection and insecure temp file naming
173
+ - Bare `except` clauses replaced throughout
174
+ - Raise-string bugs fixed
175
+ - Improper detection corrected
176
+
177
+ ---
@@ -0,0 +1,67 @@
1
+ # Contributing to mdinterface
2
+
3
+ ## Development setup
4
+
5
+ Create and activate a Python environment, then install the package with its test dependencies in editable mode. This also installs the upstream PACKMOL package and executable:
6
+
7
+ ```bash
8
+ pip install -e .[test]
9
+ ```
10
+
11
+ Install optional dependencies only when working on the corresponding feature:
12
+
13
+ ```bash
14
+ pip install -e .[resp]
15
+ pip install -e .[aimd]
16
+ ```
17
+
18
+ RESP fitting also requires the platform-specific `gpu4pyscf` package, which is not installed by the `resp` extra.
19
+
20
+ Install `libarvo` separately when working on molecular volume or radius estimation.
21
+
22
+ ### Full parameterization environment
23
+
24
+ Use the reproducible full environment when working on LigParGen, BOSS integration, or the planned OpenFF backend:
25
+
26
+ ```bash
27
+ mamba env create -f environment-full.yml
28
+ mamba activate mdinterface-full
29
+ ```
30
+
31
+ The environment uses Python 3.12 and NumPy 1.x for compatibility with the current AmberTools dependency stack. It includes CPU-only NAGL and PyTorch, AmberTools, Open Babel, OpenFF Toolkit and Interchange, PACKMOL, tests, and documentation tooling. It installs the mdinterface-compatible LigParGen fork from GitHub at the verified commit pinned in `environment-full.yml`. Developers with a sibling LigParGen checkout containing commit `ad78036` (chemistry-preserving atom reordering) can use it instead:
32
+
33
+ ```bash
34
+ python -m pip install -e ../ligpargen
35
+ ```
36
+
37
+ BOSS is never included in the environment and must be obtained and configured separately. Set `BOSSdir` in the platform-specific mdinterface `config.ini` or export it before running LigParGen tests.
38
+
39
+ ## Tests
40
+
41
+ Run the relevant test module while developing, then run the complete suite before submitting a change:
42
+
43
+ ```bash
44
+ pytest -q tests/test_builder.py
45
+ pytest -q
46
+ ```
47
+
48
+ Tests marked `integration` execute PACKMOL. Run only unit tests with `pytest -q -m "not integration"` or only integration tests with `pytest -q -m integration`. Changes to LAMMPS output should verify section structure and counts, and should load the generated data with LAMMPS when that executable is available.
49
+
50
+ Generate an informational coverage report with `pytest -q --cov=mdinterface --cov-report=term-missing`. The project does not currently enforce a coverage threshold.
51
+
52
+ ## Documentation
53
+
54
+ Install the documentation dependencies and build the site with warnings treated strictly:
55
+
56
+ ```bash
57
+ pip install -r docs/requirements.txt
58
+ mkdocs build --strict
59
+ ```
60
+
61
+ Update the relevant guide when changing a documented public API or workflow. API reference pages are generated from NumPy-style docstrings, so keep public docstrings current.
62
+
63
+ ## Changelog
64
+
65
+ Add every user-visible change to `CHANGELOG.md` under `Unreleased`, grouped under `Added`, `Changed`, `Fixed`, or `Deprecated`. Write one concise, unwrapped sentence per bullet and describe one observable change. Omit internal refactoring, agent instructions, contributor-only documentation, CI maintenance, and release-process changes unless they affect what package users install or receive.
66
+
67
+ See `docs/development/releasing.md` for the release process.
@@ -1,17 +1,22 @@
1
1
  # Include important files
2
2
  include README.md
3
3
  include LICENSE
4
+ include CHANGELOG.md
5
+ include CONTRIBUTING.md
4
6
  include requirements.txt
5
7
  include pyproject.toml
8
+ include environment-full.yml
9
+ include mkdocs.yml
6
10
 
7
11
  # Include package data
8
12
  recursive-include mdinterface *.py
9
- recursive-include mdinterface/database *.json *.txt *.dat
10
- recursive-include mdinterface/examples *.py
11
- recursive-include mdinterface/config *.ini
13
+ include mdinterface/config.ini
12
14
 
13
- # Include documentation and assets if they exist
15
+ # Include development material in the source distribution
14
16
  recursive-include docs *
17
+ recursive-include examples *
18
+ recursive-include scripts *.py
19
+ recursive-include tests *.py
15
20
  include assets/*
16
21
 
17
22
  # Exclude unwanted files
@@ -24,3 +29,4 @@ recursive-exclude * *.py[co]
24
29
  recursive-exclude * .git*
25
30
  recursive-exclude * .tox*
26
31
  recursive-exclude * .pytest_cache*
32
+ prune docs/superpowers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mdinterface
3
- Version: 1.5.3
3
+ Version: 2.0.0
4
4
  Summary: Build Interface Systems for Molecular Dynamics Simulations
5
5
  Author-email: Fabrice Roncoroni <fabrice.roncoroni@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -13,15 +13,15 @@ Classifier: Development Status :: 4 - Beta
13
13
  Classifier: Intended Audience :: Science/Research
14
14
  Classifier: Operating System :: OS Independent
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
16
  Classifier: Programming Language :: Python :: 3.10
19
17
  Classifier: Programming Language :: Python :: 3.11
20
18
  Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
21
  Classifier: Topic :: Scientific/Engineering
22
22
  Classifier: Topic :: Scientific/Engineering :: Chemistry
23
23
  Classifier: Topic :: Scientific/Engineering :: Physics
24
- Requires-Python: >=3.8
24
+ Requires-Python: >=3.10
25
25
  Description-Content-Type: text/markdown
26
26
  License-File: LICENSE
27
27
  Requires-Dist: mdanalysis>=2.0.0
@@ -30,11 +30,16 @@ Requires-Dist: numpy>=1.20.0
30
30
  Requires-Dist: networkx>=2.5
31
31
  Requires-Dist: platformdirs>=2.0.0
32
32
  Requires-Dist: configparser>=5.0.0
33
+ Requires-Dist: packmol>=21.2.3
34
+ Requires-Dist: rdkit>=2024.3.5
33
35
  Provides-Extra: resp
34
36
  Requires-Dist: pyscf>=2.0.0; extra == "resp"
35
37
  Requires-Dist: pymbxas; extra == "resp"
36
38
  Provides-Extra: aimd
37
39
  Requires-Dist: fairchem-core; extra == "aimd"
40
+ Provides-Extra: test
41
+ Requires-Dist: pytest>=7; extra == "test"
42
+ Requires-Dist: pytest-cov>=4; extra == "test"
38
43
  Provides-Extra: all
39
44
  Requires-Dist: pyscf>=2.0.0; extra == "all"
40
45
  Requires-Dist: pymbxas; extra == "all"
@@ -67,19 +72,32 @@ Dynamic: license-file
67
72
 
68
73
  ## Requirements
69
74
 
70
- Check [requirements.txt](requirements.txt) for mandatory dependencies. `pip install mdinterface` handles them automatically.
75
+ Mandatory dependencies are declared in [pyproject.toml](pyproject.toml). `pip install mdinterface` installs them automatically, including RDKit and the upstream PACKMOL package and executable; [requirements.txt](requirements.txt) is a convenience list of the same core dependencies.
71
76
 
72
- You also need `packmol` installed and on your `PATH`:
77
+ ### Optional packages
78
+
79
+ #### Molecular volume estimation
80
+
81
+ `Specie.estimate_specie_volume()` and `Specie.estimate_specie_radius()` require `libarvo`:
73
82
 
74
83
  ```bash
75
- conda install -c conda-forge packmol
84
+ pip install libarvo
76
85
  ```
77
86
 
78
- ### Optional packages
79
-
80
87
  #### LigParGen (automatic OPLS-AA parameters)
81
88
 
82
- Follow the instructions on the [LigParGen GitHub](https://github.com/Isra3l/ligpargen) (or try [this fork](https://github.com/roncofaber/ligpargen) if you hit installation issues). Point `mdinterface` to your BOSS backend via `config.ini`:
89
+ Install the [mdinterface-compatible LigParGen fork](https://github.com/roncofaber/ligpargen) in the same environment and verify that `ligpargen -h` works:
90
+
91
+ ```bash
92
+ python -m pip install "git+https://github.com/roncofaber/ligpargen.git@ad78036842318f166531be41cfcbc3563d7c5476"
93
+ conda install -c conda-forge openbabel
94
+ ligpargen -h
95
+ obabel -V
96
+ ```
97
+
98
+ The pinned LigParGen revision preserves molecular chemistry during atom reordering. Open Babel is needed for coordinate-only ASE inputs; RDKit-backed inputs use MOL files.
99
+
100
+ Point `mdinterface` to your BOSS backend via `config.ini`:
83
101
 
84
102
  ```ini
85
103
  # ~/.config/mdinterface/config.ini (path is OS-dependent)
@@ -89,11 +107,26 @@ BOSSdir = /path/to/boss # native directory
89
107
  # BOSSdir = boss-container:latest # Docker image
90
108
  ```
91
109
 
110
+ The configuration file is read when LigParGen is invoked. An existing `BOSSdir` environment variable takes precedence over the file value.
111
+
92
112
  BOSS is a 32-bit binary that can be awkward to run on modern systems. The [boss-container](https://github.com/roncofaber/boss-container) repo provides a ready-to-build Docker/Apptainer image that handles the 32-bit library setup.
93
113
 
114
+ The container recipe does not distribute BOSS. Each licensed user builds a private image from their own BOSS installation. The resulting Docker image or Apptainer file contains BOSS and must not be published or shared beyond what the BOSS license permits.
115
+
116
+ #### Full parameterization development environment
117
+
118
+ The reproducible development environment combines mdinterface, LigParGen, Open Babel, AmberTools, and the CPU-only OpenFF stack. It uses Python 3.12 and NumPy 1.x to satisfy the current AmberTools dependency stack; the core package still supports Python 3.10-3.14.
119
+
120
+ ```bash
121
+ mamba env create -f environment-full.yml
122
+ mamba activate mdinterface-full
123
+ ```
124
+
125
+ OpenFF-to-mdinterface parameter import has been validated on Python 3.14, but OpenFF is not yet exposed as a supported `Specie` parameterization backend. The environment exists for developing and testing that integration. The normal mdinterface installation remains pip-installable and does not require OpenFF.
126
+
94
127
  #### RESP charges with PySCF
95
128
 
96
- Install [PySCF](https://github.com/pyscf/pyscf) and [PyMBXAS](https://gitlab.com/roncofaber/pymbxas). RESP fitting currently requires [gpu4pyscf](https://github.com/pyscf/gpu4pyscf).
129
+ Install the `resp` extra for PySCF and PyMBXAS. RESP fitting currently also requires the platform-specific [gpu4pyscf](https://github.com/pyscf/gpu4pyscf), which is not installed by the extra.
97
130
 
98
131
  #### AIMD with FAIRChem
99
132
 
@@ -103,8 +136,7 @@ pip install fairchem-core
103
136
 
104
137
  ## Installation
105
138
 
106
- - **Python** 3.8+
107
- - **PACKMOL** (see above)
139
+ - **Python** 3.10-3.14
108
140
 
109
141
  ```bash
110
142
  # Stable release
@@ -124,6 +156,10 @@ pip install mdinterface[aimd] # FAIRChem AIMD
124
156
  pip install mdinterface[all] # everything
125
157
  ```
126
158
 
159
+ The `resp` and `all` extras do not install `gpu4pyscf`; install the compatible build separately when using RESP fitting.
160
+
161
+ Contributors working on every parameterization backend can instead create the full environment described above with `mamba env create -f environment-full.yml`.
162
+
127
163
  ## Quick start
128
164
 
129
165
  ```python
@@ -138,7 +174,7 @@ simbox.add_slab(gold, nlayers=3)
138
174
  simbox.add_solvent(water, zdim=20, density=1.0)
139
175
  simbox.build()
140
176
 
141
- atoms = simbox.to_ase() # ase.Atoms — ready for AIMD, ML-MD, or any other tool
177
+ atoms = simbox.to_ase() # ase.Atoms, ready for AIMD, ML-MD, or any other tool
142
178
  ```
143
179
 
144
180
  For LAMMPS, add ions and call `write_lammps()` instead:
@@ -162,15 +198,34 @@ More complete scripts are in the [examples/](examples/) directory:
162
198
  | Script | What it shows |
163
199
  |--------|--------------|
164
200
  | `electrode_interface.py` | Au / NaCl electrolyte / Au sandwich |
201
+ | `smiles_box.py` | Unparameterized ethanol packing from SMILES |
165
202
  | `solvent_box.py` | Pure solvent + dissolved species |
166
203
  | `multisolvent_box.py` | Mixed-solvent box with ratio/density/count modes |
167
204
  | `multilayer.py` | Five-layer multi-slab system |
168
205
  | `sandwich_from_traj.py` | Electrode / membrane / electrode sandwich from an equilibrated MD trajectory |
169
- | `polymer/polymer_piperion.py` | Co-polymer membrane box with explicit hydration number |
206
+ | `polymer/polymer_from_smiles.py` | Mapped-SMILES attachment sites, charged polymer preparation, and neutralized LAMMPS export |
207
+ | `polymer/polymer_piperion.py` | RDKit chain geometry, LigParGen junction refinement with charge audit, and hydrated membrane packing |
170
208
 
171
209
  Full API reference and user guide: [roncofaber.github.io/mdinterface](https://roncofaber.github.io/mdinterface)
172
210
 
173
- The legacy `SimulationBox` API is still available and unchanged; see [examples/legacy/](examples/legacy/).
211
+ Development setup and contribution guidance are in [CONTRIBUTING.md](CONTRIBUTING.md).
212
+
213
+ Version 2.0.0 removes `SimulationBox` and `BoxBuilder`; use `SimCell`. See the [2.0 migration guide](docs/guide/migration-2.md) for API replacements and coordinate changes.
214
+
215
+ For molecular and polymer preparation, parameterized monomers carry their force-field data into the chain:
216
+
217
+ ```python
218
+ from mdinterface import Specie, Polymer
219
+
220
+ monomer = Specie(smiles="[CH3:1][CH3:2]")
221
+ monomer.parameterize()
222
+ monomer.mark_attachment_sites(head_map=1, tail_map=2)
223
+ chain = Polymer(monomer, nrep=3)
224
+ chain.generate_conformer(seed=42, minimize=True)
225
+ report = chain.refine_junctions(charge_correction="uniform")
226
+ ```
227
+
228
+ See the [polymer guide](https://roncofaber.github.io/mdinterface/guide/polymer/) for preparation, charge auditing, and export validation. Parameterization requires LigParGen and BOSS.
174
229
 
175
230
  ## Roadmap
176
231
 
@@ -24,19 +24,32 @@
24
24
 
25
25
  ## Requirements
26
26
 
27
- Check [requirements.txt](requirements.txt) for mandatory dependencies. `pip install mdinterface` handles them automatically.
27
+ Mandatory dependencies are declared in [pyproject.toml](pyproject.toml). `pip install mdinterface` installs them automatically, including RDKit and the upstream PACKMOL package and executable; [requirements.txt](requirements.txt) is a convenience list of the same core dependencies.
28
28
 
29
- You also need `packmol` installed and on your `PATH`:
29
+ ### Optional packages
30
+
31
+ #### Molecular volume estimation
32
+
33
+ `Specie.estimate_specie_volume()` and `Specie.estimate_specie_radius()` require `libarvo`:
30
34
 
31
35
  ```bash
32
- conda install -c conda-forge packmol
36
+ pip install libarvo
33
37
  ```
34
38
 
35
- ### Optional packages
36
-
37
39
  #### LigParGen (automatic OPLS-AA parameters)
38
40
 
39
- Follow the instructions on the [LigParGen GitHub](https://github.com/Isra3l/ligpargen) (or try [this fork](https://github.com/roncofaber/ligpargen) if you hit installation issues). Point `mdinterface` to your BOSS backend via `config.ini`:
41
+ Install the [mdinterface-compatible LigParGen fork](https://github.com/roncofaber/ligpargen) in the same environment and verify that `ligpargen -h` works:
42
+
43
+ ```bash
44
+ python -m pip install "git+https://github.com/roncofaber/ligpargen.git@ad78036842318f166531be41cfcbc3563d7c5476"
45
+ conda install -c conda-forge openbabel
46
+ ligpargen -h
47
+ obabel -V
48
+ ```
49
+
50
+ The pinned LigParGen revision preserves molecular chemistry during atom reordering. Open Babel is needed for coordinate-only ASE inputs; RDKit-backed inputs use MOL files.
51
+
52
+ Point `mdinterface` to your BOSS backend via `config.ini`:
40
53
 
41
54
  ```ini
42
55
  # ~/.config/mdinterface/config.ini (path is OS-dependent)
@@ -46,11 +59,26 @@ BOSSdir = /path/to/boss # native directory
46
59
  # BOSSdir = boss-container:latest # Docker image
47
60
  ```
48
61
 
62
+ The configuration file is read when LigParGen is invoked. An existing `BOSSdir` environment variable takes precedence over the file value.
63
+
49
64
  BOSS is a 32-bit binary that can be awkward to run on modern systems. The [boss-container](https://github.com/roncofaber/boss-container) repo provides a ready-to-build Docker/Apptainer image that handles the 32-bit library setup.
50
65
 
66
+ The container recipe does not distribute BOSS. Each licensed user builds a private image from their own BOSS installation. The resulting Docker image or Apptainer file contains BOSS and must not be published or shared beyond what the BOSS license permits.
67
+
68
+ #### Full parameterization development environment
69
+
70
+ The reproducible development environment combines mdinterface, LigParGen, Open Babel, AmberTools, and the CPU-only OpenFF stack. It uses Python 3.12 and NumPy 1.x to satisfy the current AmberTools dependency stack; the core package still supports Python 3.10-3.14.
71
+
72
+ ```bash
73
+ mamba env create -f environment-full.yml
74
+ mamba activate mdinterface-full
75
+ ```
76
+
77
+ OpenFF-to-mdinterface parameter import has been validated on Python 3.14, but OpenFF is not yet exposed as a supported `Specie` parameterization backend. The environment exists for developing and testing that integration. The normal mdinterface installation remains pip-installable and does not require OpenFF.
78
+
51
79
  #### RESP charges with PySCF
52
80
 
53
- Install [PySCF](https://github.com/pyscf/pyscf) and [PyMBXAS](https://gitlab.com/roncofaber/pymbxas). RESP fitting currently requires [gpu4pyscf](https://github.com/pyscf/gpu4pyscf).
81
+ Install the `resp` extra for PySCF and PyMBXAS. RESP fitting currently also requires the platform-specific [gpu4pyscf](https://github.com/pyscf/gpu4pyscf), which is not installed by the extra.
54
82
 
55
83
  #### AIMD with FAIRChem
56
84
 
@@ -60,8 +88,7 @@ pip install fairchem-core
60
88
 
61
89
  ## Installation
62
90
 
63
- - **Python** 3.8+
64
- - **PACKMOL** (see above)
91
+ - **Python** 3.10-3.14
65
92
 
66
93
  ```bash
67
94
  # Stable release
@@ -81,6 +108,10 @@ pip install mdinterface[aimd] # FAIRChem AIMD
81
108
  pip install mdinterface[all] # everything
82
109
  ```
83
110
 
111
+ The `resp` and `all` extras do not install `gpu4pyscf`; install the compatible build separately when using RESP fitting.
112
+
113
+ Contributors working on every parameterization backend can instead create the full environment described above with `mamba env create -f environment-full.yml`.
114
+
84
115
  ## Quick start
85
116
 
86
117
  ```python
@@ -95,7 +126,7 @@ simbox.add_slab(gold, nlayers=3)
95
126
  simbox.add_solvent(water, zdim=20, density=1.0)
96
127
  simbox.build()
97
128
 
98
- atoms = simbox.to_ase() # ase.Atoms — ready for AIMD, ML-MD, or any other tool
129
+ atoms = simbox.to_ase() # ase.Atoms, ready for AIMD, ML-MD, or any other tool
99
130
  ```
100
131
 
101
132
  For LAMMPS, add ions and call `write_lammps()` instead:
@@ -119,15 +150,34 @@ More complete scripts are in the [examples/](examples/) directory:
119
150
  | Script | What it shows |
120
151
  |--------|--------------|
121
152
  | `electrode_interface.py` | Au / NaCl electrolyte / Au sandwich |
153
+ | `smiles_box.py` | Unparameterized ethanol packing from SMILES |
122
154
  | `solvent_box.py` | Pure solvent + dissolved species |
123
155
  | `multisolvent_box.py` | Mixed-solvent box with ratio/density/count modes |
124
156
  | `multilayer.py` | Five-layer multi-slab system |
125
157
  | `sandwich_from_traj.py` | Electrode / membrane / electrode sandwich from an equilibrated MD trajectory |
126
- | `polymer/polymer_piperion.py` | Co-polymer membrane box with explicit hydration number |
158
+ | `polymer/polymer_from_smiles.py` | Mapped-SMILES attachment sites, charged polymer preparation, and neutralized LAMMPS export |
159
+ | `polymer/polymer_piperion.py` | RDKit chain geometry, LigParGen junction refinement with charge audit, and hydrated membrane packing |
127
160
 
128
161
  Full API reference and user guide: [roncofaber.github.io/mdinterface](https://roncofaber.github.io/mdinterface)
129
162
 
130
- The legacy `SimulationBox` API is still available and unchanged; see [examples/legacy/](examples/legacy/).
163
+ Development setup and contribution guidance are in [CONTRIBUTING.md](CONTRIBUTING.md).
164
+
165
+ Version 2.0.0 removes `SimulationBox` and `BoxBuilder`; use `SimCell`. See the [2.0 migration guide](docs/guide/migration-2.md) for API replacements and coordinate changes.
166
+
167
+ For molecular and polymer preparation, parameterized monomers carry their force-field data into the chain:
168
+
169
+ ```python
170
+ from mdinterface import Specie, Polymer
171
+
172
+ monomer = Specie(smiles="[CH3:1][CH3:2]")
173
+ monomer.parameterize()
174
+ monomer.mark_attachment_sites(head_map=1, tail_map=2)
175
+ chain = Polymer(monomer, nrep=3)
176
+ chain.generate_conformer(seed=42, minimize=True)
177
+ report = chain.refine_junctions(charge_correction="uniform")
178
+ ```
179
+
180
+ See the [polymer guide](https://roncofaber.github.io/mdinterface/guide/polymer/) for preparation, charge auditing, and export validation. Parameterization requires LigParGen and BOSS.
131
181
 
132
182
  ## Roadmap
133
183
 
@@ -4,6 +4,10 @@ Optional integrations with third-party tools.
4
4
 
5
5
  ## LigParGen (OPLS-AA parameters)
6
6
 
7
+ ::: mdinterface.externals.ligpargen.LigParGenError
8
+
9
+ ::: mdinterface.externals.ligpargen.run_ligpargen
10
+
7
11
  ::: mdinterface.externals.ligpargen.refine_large_specie_topology
8
12
 
9
13
  ## RESP charges (PySCF)
@@ -1,5 +1,9 @@
1
1
  # I/O
2
2
 
3
+ ## PACKMOL
4
+
5
+ ::: mdinterface.build.box.PackmolError
6
+
3
7
  ## Reading structures
4
8
 
5
9
  ::: mdinterface.io.read.read_lammps_data_file