mdinterface 1.3.0__tar.gz → 1.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. mdinterface-1.5.0/MANIFEST.in +26 -0
  2. mdinterface-1.5.0/PKG-INFO +197 -0
  3. mdinterface-1.5.0/README.md +153 -0
  4. mdinterface-1.5.0/assets/mdinterface.png +0 -0
  5. mdinterface-1.5.0/examples/box_builder/builder_electrode_interface.py +70 -0
  6. mdinterface-1.5.0/examples/box_builder/builder_multilayer.py +67 -0
  7. mdinterface-1.5.0/examples/box_builder/builder_multisolvent_box.py +83 -0
  8. mdinterface-1.5.0/examples/box_builder/builder_sandwich_from_traj.py +91 -0
  9. mdinterface-1.5.0/examples/box_builder/builder_solvent_box.py +50 -0
  10. mdinterface-1.5.0/examples/simulation_box/make_POSCAR.py +67 -0
  11. mdinterface-1.5.0/examples/simulation_box/make_box.py +76 -0
  12. mdinterface-1.5.0/examples/simulation_box/make_polymer.py +74 -0
  13. mdinterface-1.5.0/examples/simulation_box/make_solvent_box.py +67 -0
  14. mdinterface-1.5.0/examples/simulation_box/make_specie_ligpargen_resp.py +26 -0
  15. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/__init__.py +4 -3
  16. mdinterface-1.5.0/mdinterface/build/__init__.py +9 -0
  17. mdinterface-1.5.0/mdinterface/build/box.py +150 -0
  18. mdinterface-1.5.0/mdinterface/build/builder.py +705 -0
  19. mdinterface-1.5.0/mdinterface/build/polymerize.py +271 -0
  20. mdinterface-1.5.0/mdinterface/build/snippets.py +141 -0
  21. mdinterface-1.5.0/mdinterface/build/solvent.py +270 -0
  22. mdinterface-1.5.0/mdinterface/core/__init__.py +9 -0
  23. mdinterface-1.5.0/mdinterface/core/polymer.py +187 -0
  24. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/core/specie.py +349 -152
  25. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/core/topology.py +128 -20
  26. mdinterface-1.5.0/mdinterface/database/__init__.py +14 -0
  27. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/ions.py +6 -4
  28. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/molecules.py +7 -1
  29. mdinterface-1.5.0/mdinterface/database/nobles.py +112 -0
  30. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/__init__.py +8 -0
  31. mdinterface-1.5.0/mdinterface/externals/aimd.py +103 -0
  32. mdinterface-1.5.0/mdinterface/externals/ase.py +70 -0
  33. mdinterface-1.5.0/mdinterface/externals/ligpargen.py +109 -0
  34. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/obabel.py +11 -12
  35. mdinterface-1.5.0/mdinterface/externals/optimization.py +67 -0
  36. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/pyscf.py +1 -1
  37. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/__init__.py +2 -1
  38. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/lammpswriter.py +143 -1
  39. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/packmol.py +1 -1
  40. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/read.py +73 -3
  41. mdinterface-1.5.0/mdinterface/read/cp2ktraj.py +139 -0
  42. mdinterface-1.5.0/mdinterface/read/lammpstraj.py +73 -0
  43. mdinterface-1.5.0/mdinterface/read/read.py +270 -0
  44. mdinterface-1.5.0/mdinterface/read/trajectory.py +405 -0
  45. mdinterface-1.5.0/mdinterface/read/xyztraj.py +33 -0
  46. mdinterface-1.5.0/mdinterface/simulationbox.py +578 -0
  47. mdinterface-1.5.0/mdinterface/utils/__init__.py +17 -0
  48. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/auxiliary.py +2 -2
  49. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/graphs.py +2 -2
  50. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/map.py +58 -23
  51. mdinterface-1.5.0/mdinterface/utils/rings.py +59 -0
  52. mdinterface-1.5.0/mdinterface.egg-info/PKG-INFO +197 -0
  53. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface.egg-info/SOURCES.txt +31 -3
  54. mdinterface-1.5.0/mdinterface.egg-info/requires.txt +19 -0
  55. mdinterface-1.5.0/mdinterface.egg-info/top_level.txt +5 -0
  56. mdinterface-1.5.0/pyproject.toml +71 -0
  57. mdinterface-1.5.0/requirements.txt +7 -0
  58. mdinterface-1.5.0/setup.cfg +4 -0
  59. mdinterface-1.5.0/tests/__init__.py +0 -0
  60. mdinterface-1.5.0/tests/test_auxiliary.py +157 -0
  61. mdinterface-1.5.0/tests/test_builder.py +392 -0
  62. mdinterface-1.5.0/tests/test_database.py +175 -0
  63. mdinterface-1.5.0/tests/test_specie.py +138 -0
  64. mdinterface-1.5.0/tests/test_topology.py +101 -0
  65. mdinterface-1.3.0/MANIFEST.in +0 -1
  66. mdinterface-1.3.0/PKG-INFO +0 -158
  67. mdinterface-1.3.0/README.md +0 -126
  68. mdinterface-1.3.0/mdinterface/build/__init__.py +0 -3
  69. mdinterface-1.3.0/mdinterface/build/box.py +0 -254
  70. mdinterface-1.3.0/mdinterface/build/charges.py +0 -8
  71. mdinterface-1.3.0/mdinterface/build/polymerize.py +0 -95
  72. mdinterface-1.3.0/mdinterface/core/__init__.py +0 -9
  73. mdinterface-1.3.0/mdinterface/core/polymer.py +0 -158
  74. mdinterface-1.3.0/mdinterface/database/__init__.py +0 -12
  75. mdinterface-1.3.0/mdinterface/externals/ligpargen.py +0 -91
  76. mdinterface-1.3.0/mdinterface/simulationbox.py +0 -447
  77. mdinterface-1.3.0/mdinterface/utils/__init__.py +0 -9
  78. mdinterface-1.3.0/mdinterface.egg-info/PKG-INFO +0 -158
  79. mdinterface-1.3.0/mdinterface.egg-info/requires.txt +0 -17
  80. mdinterface-1.3.0/mdinterface.egg-info/top_level.txt +0 -1
  81. mdinterface-1.3.0/pyproject.toml +0 -3
  82. mdinterface-1.3.0/requirements.txt +0 -6
  83. mdinterface-1.3.0/setup.cfg +0 -37
  84. {mdinterface-1.3.0 → mdinterface-1.5.0}/LICENSE +0 -0
  85. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/build/continuum2sim.py +0 -0
  86. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/config.py +0 -0
  87. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/graphene.py +0 -0
  88. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/metals.py +0 -0
  89. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/draw.py +0 -0
  90. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/poisson.py +0 -0
  91. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/units.py +0 -0
  92. {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface.egg-info/dependency_links.txt +0 -0
  93. {mdinterface-1.3.0 → mdinterface-1.5.0}/setup.py +0 -0
@@ -0,0 +1,26 @@
1
+ # Include important files
2
+ include README.md
3
+ include LICENSE
4
+ include requirements.txt
5
+ include pyproject.toml
6
+
7
+ # Include package data
8
+ recursive-include mdinterface *.py
9
+ recursive-include mdinterface/database *.json *.txt *.dat
10
+ recursive-include mdinterface/examples *.py
11
+ recursive-include mdinterface/config *.ini
12
+
13
+ # Include documentation and assets if they exist
14
+ recursive-include docs *
15
+ include assets/*
16
+
17
+ # Exclude unwanted files
18
+ exclude *.pyc
19
+ exclude *~
20
+ exclude *.bak
21
+ exclude .DS_Store
22
+ recursive-exclude * __pycache__
23
+ recursive-exclude * *.py[co]
24
+ recursive-exclude * .git*
25
+ recursive-exclude * .tox*
26
+ recursive-exclude * .pytest_cache*
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: mdinterface
3
+ Version: 1.5.0
4
+ Summary: Build Interface Systems for Molecular Dynamics Simulations
5
+ Author-email: Fabrice Roncoroni <fabrice.roncoroni@gmail.com>
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://gitlab.com/roncofaber/mdinterface
8
+ Project-URL: Repository, https://gitlab.com/roncofaber/mdinterface.git
9
+ Project-URL: Documentation, https://gitlab.com/roncofaber/mdinterface
10
+ Project-URL: Bug Tracker, https://gitlab.com/roncofaber/mdinterface/-/issues
11
+ Keywords: molecular dynamics,simulation,interface,chemistry,materials science
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Science/Research
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Topic :: Scientific/Engineering
22
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
23
+ Classifier: Topic :: Scientific/Engineering :: Physics
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: mdanalysis>=2.0.0
28
+ Requires-Dist: ase>=3.22.0
29
+ Requires-Dist: numpy>=1.20.0
30
+ Requires-Dist: networkx>=2.5
31
+ Requires-Dist: platformdirs>=2.0.0
32
+ Requires-Dist: configparser>=5.0.0
33
+ Requires-Dist: libarvo
34
+ Provides-Extra: resp
35
+ Requires-Dist: pyscf>=2.0.0; extra == "resp"
36
+ Requires-Dist: pymbxas; extra == "resp"
37
+ Provides-Extra: aimd
38
+ Requires-Dist: fairchem-core; extra == "aimd"
39
+ Provides-Extra: all
40
+ Requires-Dist: pyscf>=2.0.0; extra == "all"
41
+ Requires-Dist: pymbxas; extra == "all"
42
+ Requires-Dist: fairchem-core; extra == "all"
43
+ Dynamic: license-file
44
+
45
+ <div style="display: flex; align-items: center;">
46
+ <img src="./assets/mdinterface.png" alt="Logo" width="80" style="margin-right: 10px;">
47
+ <div style="display: flex; flex-direction: column;">
48
+ <h1 style="margin: 0;">mdinterface: Build Interface Systems for Molecular Dynamics Simulations</h1>
49
+ </div>
50
+ </div>
51
+
52
+ [![PyPI version](https://badge.fury.io/py/mdinterface.svg?icon=si%3Apython)](https://pypi.org/project/mdinterface/) [![GitHub version](https://badge.fury.io/gh/roncofaber%2Fmdinterface.svg?icon=si%3Agithub)](https://github.com/roncofaber/mdinterface)
53
+
54
+ `mdinterface` is a Python package for building systems for Molecular Dynamics (MD) simulations. Initially developed for electrolyte/electrode solid-liquid interfaces, it is equally suited for pure solvent boxes, mixed-solvent electrolytes, and polymer networks.
55
+
56
+ ## Features
57
+
58
+ - **Fluent `BoxBuilder` API** -- stack slabs, solvent regions, and vacuum gaps layer by layer; call `.build()` when done.
59
+ - **Multi-solvent support** -- mix solvents by molar ratio + density, ratio + total count, or explicit per-species molecule counts.
60
+ - **Ion placement** -- dissolve ions by count, molar concentration, or a spatially-varying concentration profile.
61
+ - **PACKMOL integration** -- handles molecular packing automatically; tolerance and dilation are tunable per layer.
62
+ - **Force-field database** -- pre-defined parameters for common metals, noble gases, water models, and ions; or generate OPLS-AA parameters on the fly with [LigParGen](https://github.com/Isra3l/ligpargen).
63
+ - **Polymer builder** -- generate chains of arbitrary length from a monomer `Specie`.
64
+ - **RESP charges** -- estimate partial charges with [PySCF](https://github.com/pyscf/pyscf) / [gpu4pyscf](https://github.com/pyscf/gpu4pyscf) (optional).
65
+ - **AIMD with FAIRChem** -- run ML-potential dynamics via [FAIRChem](https://github.com/facebookresearch/fairchem) (optional).
66
+ - **LAMMPS output** -- writes data files and force-field coefficient blocks ready to run.
67
+ - **MDAnalysis integration** -- every object converts to `mda.Universe` with a single call.
68
+
69
+ ## Requirements
70
+
71
+ Check [requirements.txt](requirements.txt) for mandatory dependencies. `pip install mdinterface` handles them automatically.
72
+
73
+ You also need `packmol` installed and on your `PATH`:
74
+
75
+ ```bash
76
+ conda install -c conda-forge packmol
77
+ ```
78
+
79
+ ### Optional packages
80
+
81
+ #### LigParGen (automatic OPLS-AA parameters)
82
+
83
+ 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 directory via `config.ini`:
84
+
85
+ ```ini
86
+ # ~/.config/mdinterface/config.ini (path is OS-dependent)
87
+ [settings]
88
+ BOSSdir = /path/to/boss
89
+ ```
90
+
91
+ #### RESP charges with PySCF
92
+
93
+ Install [PySCF](https://github.com/pyscf/pyscf) and [PyMBXAS](https://gitlab.com/roncofaber/pymbxas). RESP fitting currently requires [gpu4pyscf](https://github.com/pyscf/gpu4pyscf).
94
+
95
+ #### AIMD with FAIRChem
96
+
97
+ ```bash
98
+ pip install fairchem-core
99
+ ```
100
+
101
+ ## Installation
102
+
103
+ - **Python** 3.8+
104
+ - **PACKMOL** (see above)
105
+
106
+ ```bash
107
+ # Stable release
108
+ pip install mdinterface
109
+
110
+ # Development version
111
+ git clone https://github.com/roncofaber/mdinterface.git
112
+ cd mdinterface
113
+ pip install -e .
114
+ ```
115
+
116
+ Optional extras:
117
+
118
+ ```bash
119
+ pip install mdinterface[resp] # RESP charge analysis
120
+ pip install mdinterface[aimd] # FAIRChem AIMD
121
+ pip install mdinterface[all] # everything
122
+ ```
123
+
124
+ ## Quick start
125
+
126
+ ### Define species
127
+
128
+ ```python
129
+ from mdinterface import BoxBuilder
130
+ from mdinterface.database import Water, Ion, Metal111
131
+
132
+ water = Water(model="ewald")
133
+ na = Ion("Na", ffield="Cheatham")
134
+ cl = Ion("Cl", ffield="Cheatham")
135
+ gold = Metal111("Au")
136
+ ```
137
+
138
+ ### Build a gold / NaCl electrolyte / gold sandwich
139
+
140
+ ```python
141
+ simbox = BoxBuilder(xysize=[15, 15], verbose=True)
142
+
143
+ simbox.add_slab(gold, nlayers=3)
144
+ simbox.add_solvent(water, ions=[na, cl], nions=[5, 5], zdim=25, density=1.0)
145
+ simbox.add_slab(gold, nlayers=3)
146
+ simbox.add_vacuum(zdim=5)
147
+
148
+ simbox.build(padding=0.5)
149
+ simbox.write_lammps("data.lammps", atom_style="full", write_coeff=True)
150
+ ```
151
+
152
+ ### Mixed-solvent box (water + methanol)
153
+
154
+ ```python
155
+ from mdinterface.core.specie import Specie
156
+
157
+ methanol = Specie("CH3OH", ligpargen=True)
158
+
159
+ simbox = BoxBuilder(xysize=[25, 25])
160
+ simbox.add_solvent(
161
+ [water, methanol],
162
+ ratio=[3, 1], # 3 water : 1 methanol by mole
163
+ density=0.95,
164
+ zdim=30,
165
+ ions=[na, cl],
166
+ nions=[5, 5],
167
+ )
168
+ simbox.build(padding=0.5)
169
+ simbox.write_lammps("data_mixture.lammps", atom_style="full", write_coeff=True)
170
+ ```
171
+
172
+ ### Convert to ASE or MDAnalysis
173
+
174
+ ```python
175
+ atoms = simbox.to_ase() # ase.Atoms with cell and PBC
176
+ universe = simbox.universe # mda.Universe
177
+ ```
178
+
179
+ See the [examples/box_builder/](examples/box_builder/) directory for more complete scripts:
180
+
181
+ | Script | What it shows |
182
+ |--------|--------------|
183
+ | `builder_electrode_interface.py` | Au / NaCl electrolyte / Au sandwich |
184
+ | `builder_solvent_box.py` | Pure solvent + dissolved species |
185
+ | `builder_multisolvent_box.py` | Mixed-solvent box with ratio/density/count modes |
186
+ | `builder_multilayer.py` | Five-layer multi-slab system |
187
+ | `builder_sandwich_from_traj.py` | Load a relaxed structure via `hijack` |
188
+
189
+ The legacy `SimulationBox` API is still available and unchanged; see [examples/simulation_box/](examples/simulation_box/).
190
+
191
+ ## Roadmap
192
+
193
+ Since the original idea was to make a package to build MD boxes layer by layer, I am strongly debating renaming everything as "Workflow for Easy Molecular DYnamics Simulations", aka WEMDYS.
194
+
195
+ ## Questions & Issues
196
+
197
+ Sir, this is a WEMDY'S. Please contact me or open an issue, glad to talk about ideas and improvements!
@@ -0,0 +1,153 @@
1
+ <div style="display: flex; align-items: center;">
2
+ <img src="./assets/mdinterface.png" alt="Logo" width="80" style="margin-right: 10px;">
3
+ <div style="display: flex; flex-direction: column;">
4
+ <h1 style="margin: 0;">mdinterface: Build Interface Systems for Molecular Dynamics Simulations</h1>
5
+ </div>
6
+ </div>
7
+
8
+ [![PyPI version](https://badge.fury.io/py/mdinterface.svg?icon=si%3Apython)](https://pypi.org/project/mdinterface/) [![GitHub version](https://badge.fury.io/gh/roncofaber%2Fmdinterface.svg?icon=si%3Agithub)](https://github.com/roncofaber/mdinterface)
9
+
10
+ `mdinterface` is a Python package for building systems for Molecular Dynamics (MD) simulations. Initially developed for electrolyte/electrode solid-liquid interfaces, it is equally suited for pure solvent boxes, mixed-solvent electrolytes, and polymer networks.
11
+
12
+ ## Features
13
+
14
+ - **Fluent `BoxBuilder` API** -- stack slabs, solvent regions, and vacuum gaps layer by layer; call `.build()` when done.
15
+ - **Multi-solvent support** -- mix solvents by molar ratio + density, ratio + total count, or explicit per-species molecule counts.
16
+ - **Ion placement** -- dissolve ions by count, molar concentration, or a spatially-varying concentration profile.
17
+ - **PACKMOL integration** -- handles molecular packing automatically; tolerance and dilation are tunable per layer.
18
+ - **Force-field database** -- pre-defined parameters for common metals, noble gases, water models, and ions; or generate OPLS-AA parameters on the fly with [LigParGen](https://github.com/Isra3l/ligpargen).
19
+ - **Polymer builder** -- generate chains of arbitrary length from a monomer `Specie`.
20
+ - **RESP charges** -- estimate partial charges with [PySCF](https://github.com/pyscf/pyscf) / [gpu4pyscf](https://github.com/pyscf/gpu4pyscf) (optional).
21
+ - **AIMD with FAIRChem** -- run ML-potential dynamics via [FAIRChem](https://github.com/facebookresearch/fairchem) (optional).
22
+ - **LAMMPS output** -- writes data files and force-field coefficient blocks ready to run.
23
+ - **MDAnalysis integration** -- every object converts to `mda.Universe` with a single call.
24
+
25
+ ## Requirements
26
+
27
+ Check [requirements.txt](requirements.txt) for mandatory dependencies. `pip install mdinterface` handles them automatically.
28
+
29
+ You also need `packmol` installed and on your `PATH`:
30
+
31
+ ```bash
32
+ conda install -c conda-forge packmol
33
+ ```
34
+
35
+ ### Optional packages
36
+
37
+ #### LigParGen (automatic OPLS-AA parameters)
38
+
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 directory via `config.ini`:
40
+
41
+ ```ini
42
+ # ~/.config/mdinterface/config.ini (path is OS-dependent)
43
+ [settings]
44
+ BOSSdir = /path/to/boss
45
+ ```
46
+
47
+ #### RESP charges with PySCF
48
+
49
+ Install [PySCF](https://github.com/pyscf/pyscf) and [PyMBXAS](https://gitlab.com/roncofaber/pymbxas). RESP fitting currently requires [gpu4pyscf](https://github.com/pyscf/gpu4pyscf).
50
+
51
+ #### AIMD with FAIRChem
52
+
53
+ ```bash
54
+ pip install fairchem-core
55
+ ```
56
+
57
+ ## Installation
58
+
59
+ - **Python** 3.8+
60
+ - **PACKMOL** (see above)
61
+
62
+ ```bash
63
+ # Stable release
64
+ pip install mdinterface
65
+
66
+ # Development version
67
+ git clone https://github.com/roncofaber/mdinterface.git
68
+ cd mdinterface
69
+ pip install -e .
70
+ ```
71
+
72
+ Optional extras:
73
+
74
+ ```bash
75
+ pip install mdinterface[resp] # RESP charge analysis
76
+ pip install mdinterface[aimd] # FAIRChem AIMD
77
+ pip install mdinterface[all] # everything
78
+ ```
79
+
80
+ ## Quick start
81
+
82
+ ### Define species
83
+
84
+ ```python
85
+ from mdinterface import BoxBuilder
86
+ from mdinterface.database import Water, Ion, Metal111
87
+
88
+ water = Water(model="ewald")
89
+ na = Ion("Na", ffield="Cheatham")
90
+ cl = Ion("Cl", ffield="Cheatham")
91
+ gold = Metal111("Au")
92
+ ```
93
+
94
+ ### Build a gold / NaCl electrolyte / gold sandwich
95
+
96
+ ```python
97
+ simbox = BoxBuilder(xysize=[15, 15], verbose=True)
98
+
99
+ simbox.add_slab(gold, nlayers=3)
100
+ simbox.add_solvent(water, ions=[na, cl], nions=[5, 5], zdim=25, density=1.0)
101
+ simbox.add_slab(gold, nlayers=3)
102
+ simbox.add_vacuum(zdim=5)
103
+
104
+ simbox.build(padding=0.5)
105
+ simbox.write_lammps("data.lammps", atom_style="full", write_coeff=True)
106
+ ```
107
+
108
+ ### Mixed-solvent box (water + methanol)
109
+
110
+ ```python
111
+ from mdinterface.core.specie import Specie
112
+
113
+ methanol = Specie("CH3OH", ligpargen=True)
114
+
115
+ simbox = BoxBuilder(xysize=[25, 25])
116
+ simbox.add_solvent(
117
+ [water, methanol],
118
+ ratio=[3, 1], # 3 water : 1 methanol by mole
119
+ density=0.95,
120
+ zdim=30,
121
+ ions=[na, cl],
122
+ nions=[5, 5],
123
+ )
124
+ simbox.build(padding=0.5)
125
+ simbox.write_lammps("data_mixture.lammps", atom_style="full", write_coeff=True)
126
+ ```
127
+
128
+ ### Convert to ASE or MDAnalysis
129
+
130
+ ```python
131
+ atoms = simbox.to_ase() # ase.Atoms with cell and PBC
132
+ universe = simbox.universe # mda.Universe
133
+ ```
134
+
135
+ See the [examples/box_builder/](examples/box_builder/) directory for more complete scripts:
136
+
137
+ | Script | What it shows |
138
+ |--------|--------------|
139
+ | `builder_electrode_interface.py` | Au / NaCl electrolyte / Au sandwich |
140
+ | `builder_solvent_box.py` | Pure solvent + dissolved species |
141
+ | `builder_multisolvent_box.py` | Mixed-solvent box with ratio/density/count modes |
142
+ | `builder_multilayer.py` | Five-layer multi-slab system |
143
+ | `builder_sandwich_from_traj.py` | Load a relaxed structure via `hijack` |
144
+
145
+ The legacy `SimulationBox` API is still available and unchanged; see [examples/simulation_box/](examples/simulation_box/).
146
+
147
+ ## Roadmap
148
+
149
+ Since the original idea was to make a package to build MD boxes layer by layer, I am strongly debating renaming everything as "Workflow for Easy Molecular DYnamics Simulations", aka WEMDYS.
150
+
151
+ ## Questions & Issues
152
+
153
+ Sir, this is a WEMDY'S. Please contact me or open an issue, glad to talk about ideas and improvements!
Binary file
@@ -0,0 +1,70 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ BoxBuilder example: Au(111) / NaCl electrolyte / Au(111) sandwich.
5
+
6
+ Equivalent to make_box.py but using the fluent BoxBuilder API.
7
+ Layers are added in the order they appear in the cell (bottom → top).
8
+
9
+ Author: roncofaber
10
+ """
11
+
12
+ from mdinterface import BoxBuilder
13
+ from mdinterface.database import Water, Ion, Metal111
14
+
15
+ #%% Define species
16
+
17
+ water = Water(model="ewald")
18
+
19
+ na = Ion("Na", ffield="Cheatham")
20
+ cl = Ion("Cl", ffield="Cheatham")
21
+
22
+ gold = Metal111("Au")
23
+
24
+ #%% Set up simulation box
25
+
26
+ simbox = BoxBuilder(
27
+ xysize=[15, 15],
28
+ verbose=True, # True → INFO, "DEBUG" → DEBUG, False/None → silent
29
+ )
30
+
31
+ #%% Add layers (bottom → top)
32
+
33
+ simbox.add_slab(gold, nlayers=1)
34
+
35
+ simbox.add_solvent(
36
+ water,
37
+ ions=[na, cl],
38
+ nions=[5, 5], # 5 Na⁺ and 5 Cl⁻
39
+ zdim=25,
40
+ density=1.0,
41
+ # dilate=1.25, # for concentrated systems: packs into a box 25%
42
+ # # taller so PACKMOL has breathing room; NpT MD
43
+ # # will compress back to the correct density
44
+ # packmol_tolerance=1.5,# lower from default 2.0 Å if PACKMOL fails to pack
45
+ )
46
+
47
+ simbox.add_slab(gold, nlayers=1)
48
+
49
+ simbox.add_vacuum(zdim=5)
50
+
51
+ #%% Build
52
+
53
+ simbox.build(
54
+ padding=0.5,
55
+ center=False, # set True to center the first slab in the box
56
+ layered=False, # set True to tag each slab layer with a unique mol-id
57
+ # hijack=atoms, # override positions + cell from an external ase.Atoms
58
+ # # (e.g. a pre-relaxed slab); topology is preserved
59
+ )
60
+
61
+ #%% Output
62
+
63
+ # Write LAMMPS data file (with force-field coefficients)
64
+ simbox.write_lammps("data.lammps", atom_style="full", write_coeff=True)
65
+
66
+ # Convert to ASE Atoms (e.g. for visualisation or further manipulation)
67
+ atoms = simbox.to_ase()
68
+
69
+ # Access the raw MDAnalysis Universe if needed
70
+ universe = simbox.universe
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ BoxBuilder example: multi-layer cell with heterogeneous electrolyte regions.
5
+
6
+ This setup is impractical to express with the old SimulationBox API (which
7
+ only supports one interface, one enderface, and one miderface slot). With
8
+ BoxBuilder you can stack as many slabs and solvent regions as needed.
9
+
10
+ Layout (bottom to top):
11
+ Au(111) slab — bottom electrode
12
+ NaCl solution — first electrolyte region
13
+ Pt(111) slab — middle electrode
14
+ KF solution — second electrolyte region
15
+ Pt(111) slab — top electrode
16
+ vacuum gap
17
+
18
+ Author: roncofaber
19
+ """
20
+
21
+ from mdinterface import BoxBuilder
22
+ from mdinterface.database import Water, Ion, Metal111
23
+
24
+ #%% Define species
25
+
26
+ water = Water(model="ewald")
27
+
28
+ na = Ion("Na", ffield="Cheatham")
29
+ cl = Ion("Cl", ffield="Cheatham")
30
+ k = Ion("K", ffield="Cheatham")
31
+ f = Ion("F", ffield="Dang")
32
+
33
+ gold = Metal111("Au")
34
+ platinum = Metal111("Pt")
35
+
36
+ #%% Set up simulation box
37
+
38
+ simbox = BoxBuilder(xysize=[20, 20])
39
+
40
+ #%% Add layers (bottom → top)
41
+
42
+ simbox.add_slab(gold, nlayers=3) # bottom electrode
43
+
44
+ simbox.add_solvent(water, ions=[na, cl], nions=[4, 4], zdim=20, density=1.0) # NaCl region
45
+
46
+ simbox.add_slab(platinum, nlayers=2) # middle electrode
47
+
48
+ simbox.add_solvent(water, ions=[k, f], nions=[4, 4], zdim=20, density=1.0) # KF region
49
+
50
+ simbox.add_slab(platinum, nlayers=2) # top electrode
51
+
52
+ simbox.add_vacuum(zdim=10) # gap at periodic boundary
53
+
54
+ #%% Build
55
+
56
+ simbox.build(padding=0.5)
57
+
58
+ #%% Output
59
+
60
+ # Write LAMMPS data file (with force-field coefficients)
61
+ simbox.write_lammps("data_multilayer.lammps", atom_style="full", write_coeff=True)
62
+
63
+ # Convert to ASE Atoms (e.g. for visualisation or further manipulation)
64
+ atoms = simbox.to_ase()
65
+
66
+ # Access the raw MDAnalysis Universe if needed
67
+ universe = simbox.universe
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ BoxBuilder example: mixed-solvent box (water + methanol).
5
+
6
+ Demonstrates the three ways to specify solvent composition when multiple
7
+ solvent species are present. A dissolved NaCl salt is added on top.
8
+
9
+ Mixing modes (choose one):
10
+
11
+ A) ratio + density -- most physical: volumes/masses set the count
12
+ B) ratio + nsolvent -- fix total molecule count, split by ratio
13
+ C) nsolvent (list) -- full manual control, one count per species
14
+
15
+ Author: roncofaber
16
+ """
17
+
18
+ from mdinterface import BoxBuilder
19
+ from mdinterface.database import Water, Ion
20
+ from mdinterface.core.specie import Specie
21
+
22
+ #%% Define species
23
+
24
+ # Solvents
25
+ water = Water(model="ewald")
26
+ methanol = Specie("CH3OH", ligpargen=True)
27
+
28
+ # Dissolved ions (optional — comment out if not needed)
29
+ na = Ion("Na", ffield="Cheatham")
30
+ cl = Ion("Cl", ffield="Cheatham")
31
+
32
+ #%% Set up simulation box
33
+
34
+ simbox = BoxBuilder(
35
+ xysize=[25, 25],
36
+ verbose=True,
37
+ )
38
+
39
+ #%% Add mixed-solvent layer
40
+
41
+ # --- Mode A: ratio + density (recommended for liquid mixtures) ---
42
+ # 3 water molecules for every 1 methanol, total density 0.95 g/cm³.
43
+ # Molecule counts are derived automatically from the molar masses.
44
+ simbox.add_solvent(
45
+ [water, methanol],
46
+ ratio=[3, 1], # molar mixing ratio (water : methanol)
47
+ density=0.95, # mixture density in g/cm³
48
+ zdim=30, # region thickness in Å
49
+ ions=[na, cl],
50
+ nions=[5, 5], # 5 Na+ and 5 Cl-
51
+ )
52
+
53
+ # --- Mode B: ratio + fixed total count ---
54
+ # Uncomment to use instead of Mode A.
55
+ # simbox.add_solvent(
56
+ # [water, methanol],
57
+ # ratio=[3, 1],
58
+ # nsolvent=200, # 150 water + 50 methanol (split proportionally)
59
+ # zdim=30,
60
+ # ions=[na, cl],
61
+ # nions=[5, 5],
62
+ # )
63
+
64
+ # --- Mode C: explicit per-species counts ---
65
+ # Uncomment to use instead of Mode A.
66
+ # simbox.add_solvent(
67
+ # [water, methanol],
68
+ # nsolvent=[150, 50], # exactly 150 water and 50 methanol
69
+ # zdim=30,
70
+ # ions=[na, cl],
71
+ # nions=[5, 5],
72
+ # )
73
+
74
+ #%% Build
75
+
76
+ simbox.build(padding=0.5)
77
+
78
+ #%% Output
79
+
80
+ simbox.write_lammps("data_multisolvent.lammps", atom_style="full", write_coeff=True)
81
+
82
+ atoms = simbox.to_ase()
83
+ universe = simbox.universe
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ BoxBuilder example: Pt(111) / polymer slab / Pt(111) sandwich loaded from a
5
+ LAMMPS dump trajectory.
6
+
7
+ The polymer slab positions come from a prior MD run rather than being built
8
+ from scratch. The topology object (Specie / Polymer) is defined here — in a
9
+ real workflow it would be loaded from a pickle saved during chain building.
10
+
11
+ A minimal single-frame dump is provided in data/water_frame.dump so the
12
+ example is self-contained. Replace DUMP_FILE with the path to your own
13
+ production dump to reproduce the real workflow.
14
+
15
+ Workflow
16
+ --------
17
+ 1. Define / load the polymer topology (Specie or Polymer with FF params).
18
+ 2. Point DUMP_FILE at a LAMMPS dump from a prior MD run.
19
+ 3. Read the target frame with read_lammps_nth_frame — streams the file and
20
+ never loads the full trajectory into memory.
21
+ 4. Inject those positions into the topology object with update_positions().
22
+ 5. Stack everything with BoxBuilder as usual.
23
+
24
+ Author: roncofaber
25
+ """
26
+
27
+ from pathlib import Path
28
+
29
+ from mdinterface import BoxBuilder
30
+ from mdinterface.database import Water, Metal111
31
+ from mdinterface.io import read_lammps_nth_frame
32
+
33
+ #%% Paths
34
+
35
+ # Minimal 1-frame dump shipped with this example.
36
+ # In a real workflow: DUMP_FILE = "/path/to/production.dump"
37
+ DUMP_FILE = Path(__file__).parent / "data" / "water_frame.dump"
38
+
39
+ #%% Define species
40
+ # Water is used here as a stand-in for a Nafion polymer.
41
+ # In practice you would do: polymer = pickle.load(open("nafi_20.pkl", "rb"))
42
+
43
+ water = Water(model="ewald")
44
+ platinum = Metal111("Pt")
45
+
46
+ #%% Read one frame from the dump
47
+ # frame=-1 -> last frame (default)
48
+ # frame=0 -> first frame
49
+ # The file is streamed; only the requested frame is parsed.
50
+
51
+ last_frame = read_lammps_nth_frame(DUMP_FILE, frame=-1)
52
+
53
+ #%% Inject trajectory positions into the topology object
54
+ # prune_z=True trims any vacuum that accumulated during MD along z.
55
+ # The cell is also updated, so BoxBuilder picks up the correct XY dimensions.
56
+
57
+ water.update_positions(atoms=last_frame, prune_z=True)
58
+
59
+ #%% Set up simulation box
60
+ # xysize is a tiling hint for the electrode slabs.
61
+ # match_cell=water overrides the final XY to the polymer's exact cell,
62
+ # so the starting guess here only needs to be in the right ballpark.
63
+
64
+ simbox = BoxBuilder(
65
+ xysize=[20, 20],
66
+ verbose=True,
67
+ )
68
+
69
+ #%% Add layers (bottom -> top)
70
+
71
+ simbox.add_slab(platinum, nlayers=2)
72
+
73
+ simbox.add_slab(water, nlayers=1) # polymer: cell already matches, no tiling
74
+
75
+ simbox.add_slab(platinum, nlayers=2)
76
+
77
+ #%% Build
78
+ # match_cell=water locks XY to the polymer's cell.
79
+ # Pt slabs are stretched to conform; the polymer itself is left unscaled.
80
+
81
+ simbox.build(
82
+ padding=0.5,
83
+ match_cell=platinum,
84
+ )
85
+
86
+ #%% Output
87
+
88
+ simbox.write_lammps("data.lammps", atom_style="full", write_coeff=True)
89
+
90
+ atoms = simbox.to_ase()
91
+ universe = simbox.universe