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.
- mdinterface-1.5.0/MANIFEST.in +26 -0
- mdinterface-1.5.0/PKG-INFO +197 -0
- mdinterface-1.5.0/README.md +153 -0
- mdinterface-1.5.0/assets/mdinterface.png +0 -0
- mdinterface-1.5.0/examples/box_builder/builder_electrode_interface.py +70 -0
- mdinterface-1.5.0/examples/box_builder/builder_multilayer.py +67 -0
- mdinterface-1.5.0/examples/box_builder/builder_multisolvent_box.py +83 -0
- mdinterface-1.5.0/examples/box_builder/builder_sandwich_from_traj.py +91 -0
- mdinterface-1.5.0/examples/box_builder/builder_solvent_box.py +50 -0
- mdinterface-1.5.0/examples/simulation_box/make_POSCAR.py +67 -0
- mdinterface-1.5.0/examples/simulation_box/make_box.py +76 -0
- mdinterface-1.5.0/examples/simulation_box/make_polymer.py +74 -0
- mdinterface-1.5.0/examples/simulation_box/make_solvent_box.py +67 -0
- mdinterface-1.5.0/examples/simulation_box/make_specie_ligpargen_resp.py +26 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/__init__.py +4 -3
- mdinterface-1.5.0/mdinterface/build/__init__.py +9 -0
- mdinterface-1.5.0/mdinterface/build/box.py +150 -0
- mdinterface-1.5.0/mdinterface/build/builder.py +705 -0
- mdinterface-1.5.0/mdinterface/build/polymerize.py +271 -0
- mdinterface-1.5.0/mdinterface/build/snippets.py +141 -0
- mdinterface-1.5.0/mdinterface/build/solvent.py +270 -0
- mdinterface-1.5.0/mdinterface/core/__init__.py +9 -0
- mdinterface-1.5.0/mdinterface/core/polymer.py +187 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/core/specie.py +349 -152
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/core/topology.py +128 -20
- mdinterface-1.5.0/mdinterface/database/__init__.py +14 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/ions.py +6 -4
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/molecules.py +7 -1
- mdinterface-1.5.0/mdinterface/database/nobles.py +112 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/__init__.py +8 -0
- mdinterface-1.5.0/mdinterface/externals/aimd.py +103 -0
- mdinterface-1.5.0/mdinterface/externals/ase.py +70 -0
- mdinterface-1.5.0/mdinterface/externals/ligpargen.py +109 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/obabel.py +11 -12
- mdinterface-1.5.0/mdinterface/externals/optimization.py +67 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/externals/pyscf.py +1 -1
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/__init__.py +2 -1
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/lammpswriter.py +143 -1
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/packmol.py +1 -1
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/io/read.py +73 -3
- mdinterface-1.5.0/mdinterface/read/cp2ktraj.py +139 -0
- mdinterface-1.5.0/mdinterface/read/lammpstraj.py +73 -0
- mdinterface-1.5.0/mdinterface/read/read.py +270 -0
- mdinterface-1.5.0/mdinterface/read/trajectory.py +405 -0
- mdinterface-1.5.0/mdinterface/read/xyztraj.py +33 -0
- mdinterface-1.5.0/mdinterface/simulationbox.py +578 -0
- mdinterface-1.5.0/mdinterface/utils/__init__.py +17 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/auxiliary.py +2 -2
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/graphs.py +2 -2
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/map.py +58 -23
- mdinterface-1.5.0/mdinterface/utils/rings.py +59 -0
- mdinterface-1.5.0/mdinterface.egg-info/PKG-INFO +197 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface.egg-info/SOURCES.txt +31 -3
- mdinterface-1.5.0/mdinterface.egg-info/requires.txt +19 -0
- mdinterface-1.5.0/mdinterface.egg-info/top_level.txt +5 -0
- mdinterface-1.5.0/pyproject.toml +71 -0
- mdinterface-1.5.0/requirements.txt +7 -0
- mdinterface-1.5.0/setup.cfg +4 -0
- mdinterface-1.5.0/tests/__init__.py +0 -0
- mdinterface-1.5.0/tests/test_auxiliary.py +157 -0
- mdinterface-1.5.0/tests/test_builder.py +392 -0
- mdinterface-1.5.0/tests/test_database.py +175 -0
- mdinterface-1.5.0/tests/test_specie.py +138 -0
- mdinterface-1.5.0/tests/test_topology.py +101 -0
- mdinterface-1.3.0/MANIFEST.in +0 -1
- mdinterface-1.3.0/PKG-INFO +0 -158
- mdinterface-1.3.0/README.md +0 -126
- mdinterface-1.3.0/mdinterface/build/__init__.py +0 -3
- mdinterface-1.3.0/mdinterface/build/box.py +0 -254
- mdinterface-1.3.0/mdinterface/build/charges.py +0 -8
- mdinterface-1.3.0/mdinterface/build/polymerize.py +0 -95
- mdinterface-1.3.0/mdinterface/core/__init__.py +0 -9
- mdinterface-1.3.0/mdinterface/core/polymer.py +0 -158
- mdinterface-1.3.0/mdinterface/database/__init__.py +0 -12
- mdinterface-1.3.0/mdinterface/externals/ligpargen.py +0 -91
- mdinterface-1.3.0/mdinterface/simulationbox.py +0 -447
- mdinterface-1.3.0/mdinterface/utils/__init__.py +0 -9
- mdinterface-1.3.0/mdinterface.egg-info/PKG-INFO +0 -158
- mdinterface-1.3.0/mdinterface.egg-info/requires.txt +0 -17
- mdinterface-1.3.0/mdinterface.egg-info/top_level.txt +0 -1
- mdinterface-1.3.0/pyproject.toml +0 -3
- mdinterface-1.3.0/requirements.txt +0 -6
- mdinterface-1.3.0/setup.cfg +0 -37
- {mdinterface-1.3.0 → mdinterface-1.5.0}/LICENSE +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/build/continuum2sim.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/config.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/graphene.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/database/metals.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/draw.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/poisson.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface/utils/units.py +0 -0
- {mdinterface-1.3.0 → mdinterface-1.5.0}/mdinterface.egg-info/dependency_links.txt +0 -0
- {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
|
+
[](https://pypi.org/project/mdinterface/) [](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
|
+
[](https://pypi.org/project/mdinterface/) [](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
|