imdclient 0.1.4__py3-none-any.whl → 0.2.0b0__py3-none-any.whl
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.
- imdclient/IMDClient.py +24 -22
- imdclient/__init__.py +0 -5
- imdclient/data/namd/md/namd3 +0 -0
- imdclient/data/namd/md/namd_v3_nst_1.namd +1 -1
- imdclient/tests/base.py +82 -103
- imdclient/tests/datafiles.py +1 -1
- imdclient/tests/docker_testing/docker.md +1 -1
- imdclient/tests/hpc_testing/lammps/README.md +2 -2
- imdclient/tests/hpc_testing/namd/README.md +93 -19
- imdclient/tests/minimalreader.py +86 -0
- imdclient/tests/server.py +4 -3
- imdclient/tests/test_gromacs.py +15 -3
- imdclient/tests/test_imdclient.py +8 -7
- imdclient/tests/test_lammps.py +22 -19
- imdclient/tests/test_manual.py +24 -22
- imdclient/tests/test_namd.py +39 -16
- imdclient/tests/test_utils.py +31 -0
- imdclient/utils.py +50 -17
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info}/METADATA +60 -39
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info}/RECORD +24 -28
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info}/WHEEL +1 -1
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info/licenses}/AUTHORS.md +4 -1
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info/licenses}/LICENSE +3 -1
- imdclient/IMD.py +0 -132
- imdclient/backends.py +0 -352
- imdclient/results.py +0 -332
- imdclient/streamanalysis.py +0 -1056
- imdclient/streambase.py +0 -199
- imdclient/tests/test_imdreader.py +0 -717
- imdclient/tests/test_stream_analysis.py +0 -61
- {imdclient-0.1.4.dist-info → imdclient-0.2.0b0.dist-info}/top_level.txt +0 -0
imdclient/IMDClient.py
CHANGED
@@ -1,18 +1,27 @@
|
|
1
1
|
"""
|
2
|
-
|
3
|
-
|
4
|
-
^^^^^^^^^
|
2
|
+
IMDClient module
|
3
|
+
================
|
5
4
|
|
6
5
|
.. autoclass:: IMDClient
|
7
6
|
:members:
|
8
7
|
|
8
|
+
.. autoclass:: BaseIMDProducer
|
9
|
+
:members:
|
10
|
+
:inherited-members:
|
11
|
+
|
12
|
+
.. autoclass:: IMDProducerV2
|
13
|
+
:members:
|
14
|
+
:inherited-members:
|
15
|
+
|
9
16
|
.. autoclass:: IMDProducerV3
|
10
17
|
:members:
|
11
18
|
:inherited-members:
|
12
19
|
|
13
20
|
.. autoclass:: IMDFrameBuffer
|
14
21
|
:members:
|
15
|
-
|
22
|
+
|
23
|
+
.. autoclass:: IMDFrame
|
24
|
+
:members:
|
16
25
|
"""
|
17
26
|
|
18
27
|
import socket
|
@@ -43,7 +52,7 @@ class IMDClient:
|
|
43
52
|
socket_bufsize : int, (optional)
|
44
53
|
Size of the socket buffer in bytes. Default is to use the system default
|
45
54
|
buffer_size : int (optional)
|
46
|
-
|
55
|
+
:class:`IMDFrameBuffer` will be filled with as many :class:`IMDFrame` fit in `buffer_size` bytes [``10MB``]
|
47
56
|
timeout : int, optional
|
48
57
|
Timeout for the socket in seconds [``5``]
|
49
58
|
continue_after_disconnect : bool, optional [``None``]
|
@@ -138,10 +147,11 @@ class IMDClient:
|
|
138
147
|
|
139
148
|
self._producer.start()
|
140
149
|
|
141
|
-
def signal_handler(self
|
142
|
-
"""Catch SIGINT to allow clean shutdown on CTRL+C
|
150
|
+
def signal_handler(self):
|
151
|
+
"""Catch SIGINT to allow clean shutdown on CTRL+C.
|
152
|
+
|
143
153
|
This also ensures that main thread execution doesn't get stuck
|
144
|
-
waiting in buf.pop_full_imdframe()"""
|
154
|
+
waiting in ``buf.pop_full_imdframe()``"""
|
145
155
|
logger.debug("Intercepted signal")
|
146
156
|
self.stop()
|
147
157
|
logger.debug("Shutdown success")
|
@@ -207,9 +217,7 @@ class IMDClient:
|
|
207
217
|
# /proc/sys/net/core/rmem_default
|
208
218
|
# Max (linux):
|
209
219
|
# /proc/sys/net/core/rmem_max
|
210
|
-
conn.setsockopt(
|
211
|
-
socket.SOL_SOCKET, socket.SO_RCVBUF, socket_bufsize
|
212
|
-
)
|
220
|
+
conn.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, socket_bufsize)
|
213
221
|
try:
|
214
222
|
logger.debug(f"IMDClient: Connecting to {host}:{port}")
|
215
223
|
conn.connect((host, port))
|
@@ -307,8 +315,8 @@ class IMDClient:
|
|
307
315
|
)
|
308
316
|
self._conn.sendall(wait_packet)
|
309
317
|
logger.debug(
|
310
|
-
"IMDClient: Attempted to change wait behavior to %s",
|
311
|
-
not self._continue_after_disconnect
|
318
|
+
"IMDClient: Attempted to change wait behavior to %s",
|
319
|
+
not self._continue_after_disconnect,
|
312
320
|
)
|
313
321
|
|
314
322
|
def _disconnect(self):
|
@@ -785,9 +793,7 @@ class IMDFrameBuffer:
|
|
785
793
|
raise ValueError("pause_empty_proportion must be between 0 and 1")
|
786
794
|
self._pause_empty_proportion = pause_empty_proportion
|
787
795
|
if unpause_empty_proportion < 0 or unpause_empty_proportion > 1:
|
788
|
-
raise ValueError(
|
789
|
-
"unpause_empty_proportion must be between 0 and 1"
|
790
|
-
)
|
796
|
+
raise ValueError("unpause_empty_proportion must be between 0 and 1")
|
791
797
|
self._unpause_empty_proportion = unpause_empty_proportion
|
792
798
|
|
793
799
|
if buffer_size <= 0:
|
@@ -854,9 +860,7 @@ class IMDFrameBuffer:
|
|
854
860
|
logger.debug("IMDProducer: Noticing consumer finished")
|
855
861
|
raise EOFError
|
856
862
|
except Exception as e:
|
857
|
-
logger.debug(
|
858
|
-
f"IMDProducer: Error waiting for space in buffer: {e}"
|
859
|
-
)
|
863
|
+
logger.debug(f"IMDProducer: Error waiting for space in buffer: {e}")
|
860
864
|
|
861
865
|
def pop_empty_imdframe(self):
|
862
866
|
logger.debug("IMDProducer: Getting empty frame")
|
@@ -902,9 +906,7 @@ class IMDFrameBuffer:
|
|
902
906
|
imdf = self._full_q.get()
|
903
907
|
else:
|
904
908
|
with self._full_imdf_avail:
|
905
|
-
while (
|
906
|
-
self._full_q.qsize() == 0 and not self._producer_finished
|
907
|
-
):
|
909
|
+
while self._full_q.qsize() == 0 and not self._producer_finished:
|
908
910
|
self._full_imdf_avail.wait()
|
909
911
|
|
910
912
|
if self._producer_finished and self._full_q.qsize() == 0:
|
imdclient/__init__.py
CHANGED
@@ -6,9 +6,4 @@ IMDClient
|
|
6
6
|
from .IMDClient import IMDClient
|
7
7
|
from importlib.metadata import version
|
8
8
|
|
9
|
-
from .streamanalysis import AnalysisBase, StackableAnalysis
|
10
|
-
from MDAnalysis.analysis import base
|
11
|
-
|
12
|
-
base.AnalysisBase = AnalysisBase
|
13
|
-
|
14
9
|
__version__ = version("imdclient")
|
Binary file
|
imdclient/tests/base.py
CHANGED
@@ -1,20 +1,17 @@
|
|
1
|
-
from imdclient.IMDClient import IMDClient
|
2
|
-
from imdclient.IMD import IMDReader
|
3
|
-
import pytest
|
4
|
-
from pathlib import Path
|
5
|
-
import os
|
6
|
-
import signal
|
7
|
-
import subprocess
|
8
1
|
import time
|
2
|
+
import logging
|
3
|
+
import shutil
|
4
|
+
|
5
|
+
import pytest
|
6
|
+
import numpy as np
|
9
7
|
from numpy.testing import (
|
10
8
|
assert_allclose,
|
11
9
|
)
|
12
|
-
import numpy as np
|
13
10
|
import docker
|
14
|
-
import logging
|
15
|
-
import shutil
|
16
11
|
import MDAnalysis as mda
|
12
|
+
|
17
13
|
from .utils import get_free_port
|
14
|
+
from .minimalreader import MinimalReader
|
18
15
|
|
19
16
|
logger = logging.getLogger("imdclient.IMDClient")
|
20
17
|
|
@@ -64,6 +61,10 @@ def assert_allclose_with_logging(a, b, rtol=1e-07, atol=0, equal_nan=False):
|
|
64
61
|
|
65
62
|
class IMDv3IntegrationTest:
|
66
63
|
|
64
|
+
@pytest.fixture()
|
65
|
+
def container_name(self):
|
66
|
+
return "ghcr.io/becksteinlab/streaming-md-docker:main-common-cpu"
|
67
|
+
|
67
68
|
@pytest.fixture()
|
68
69
|
def setup_command(self):
|
69
70
|
return None
|
@@ -80,12 +81,13 @@ class IMDv3IntegrationTest:
|
|
80
81
|
setup_command,
|
81
82
|
simulation_command,
|
82
83
|
port,
|
84
|
+
container_name,
|
83
85
|
):
|
84
86
|
# In CI, container process needs access to tmp_path
|
85
87
|
tmp_path.chmod(0o777)
|
86
88
|
docker_client = docker.from_env()
|
87
89
|
img = docker_client.images.pull(
|
88
|
-
|
90
|
+
container_name,
|
89
91
|
)
|
90
92
|
# Copy input files into tmp_path
|
91
93
|
for inp in input_files:
|
@@ -123,13 +125,11 @@ class IMDv3IntegrationTest:
|
|
123
125
|
|
124
126
|
@pytest.fixture()
|
125
127
|
def imd_u(self, docker_client, topol, tmp_path, port):
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
)
|
130
|
-
|
131
|
-
w.write(u.atoms)
|
132
|
-
yield mda.Universe((tmp_path / topol), (tmp_path / "imd.trr"))
|
128
|
+
n_atoms = mda.Universe(tmp_path / topol).atoms.n_atoms
|
129
|
+
u = MinimalReader(
|
130
|
+
f"imd://localhost:{port}", n_atoms=n_atoms, process_stream=True
|
131
|
+
)
|
132
|
+
yield u
|
133
133
|
|
134
134
|
@pytest.fixture()
|
135
135
|
def true_u(self, topol, traj, imd_u, tmp_path):
|
@@ -139,118 +139,97 @@ class IMDv3IntegrationTest:
|
|
139
139
|
)
|
140
140
|
yield u
|
141
141
|
|
142
|
-
|
143
|
-
|
144
|
-
return True
|
142
|
+
def test_compare_imd_to_true_traj(self, imd_u, true_u, first_frame, dt):
|
143
|
+
for i in range(first_frame, len(true_u.trajectory)):
|
145
144
|
|
146
|
-
|
147
|
-
|
148
|
-
|
145
|
+
assert_allclose(
|
146
|
+
true_u.trajectory[i].time,
|
147
|
+
imd_u.trajectory[i - first_frame].time,
|
148
|
+
atol=1e-03,
|
149
|
+
)
|
149
150
|
|
150
|
-
|
151
|
-
|
152
|
-
|
151
|
+
assert_allclose(
|
152
|
+
dt,
|
153
|
+
imd_u.trajectory[i - first_frame].dt,
|
154
|
+
atol=1e-03,
|
155
|
+
)
|
153
156
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
atol=1e-03,
|
183
|
-
)
|
184
|
-
if (
|
185
|
-
true_u.trajectory[i].has_positions
|
186
|
-
and imd_u.trajectory[i - first_frame].has_positions
|
187
|
-
):
|
188
|
-
assert_allclose_with_logging(
|
189
|
-
true_u.trajectory[i].positions,
|
190
|
-
imd_u.trajectory[i - first_frame].positions,
|
191
|
-
atol=1e-03,
|
192
|
-
)
|
193
|
-
if (
|
194
|
-
true_u.trajectory[i].has_velocities
|
195
|
-
and imd_u.trajectory[i - first_frame].has_velocities
|
196
|
-
):
|
197
|
-
assert_allclose_with_logging(
|
198
|
-
true_u.trajectory[i].velocities,
|
199
|
-
imd_u.trajectory[i - first_frame].velocities,
|
200
|
-
atol=1e-03,
|
201
|
-
)
|
202
|
-
if (
|
203
|
-
true_u.trajectory[i].has_forces
|
204
|
-
and imd_u.trajectory[i - first_frame].has_forces
|
205
|
-
):
|
206
|
-
assert_allclose_with_logging(
|
207
|
-
true_u.trajectory[i].forces,
|
208
|
-
imd_u.trajectory[i - first_frame].forces,
|
209
|
-
atol=1e-03,
|
210
|
-
)
|
157
|
+
assert_allclose(
|
158
|
+
true_u.trajectory[i].data["step"],
|
159
|
+
imd_u.trajectory[i - first_frame].step,
|
160
|
+
)
|
161
|
+
|
162
|
+
assert_allclose_with_logging(
|
163
|
+
true_u.trajectory[i].dimensions,
|
164
|
+
imd_u.trajectory[i - first_frame].dimensions,
|
165
|
+
atol=1e-03,
|
166
|
+
)
|
167
|
+
|
168
|
+
assert_allclose_with_logging(
|
169
|
+
true_u.trajectory[i].positions,
|
170
|
+
imd_u.trajectory[i - first_frame].positions,
|
171
|
+
atol=1e-03,
|
172
|
+
)
|
173
|
+
|
174
|
+
assert_allclose_with_logging(
|
175
|
+
true_u.trajectory[i].velocities,
|
176
|
+
imd_u.trajectory[i - first_frame].velocities,
|
177
|
+
atol=1e-03,
|
178
|
+
)
|
179
|
+
|
180
|
+
assert_allclose_with_logging(
|
181
|
+
true_u.trajectory[i].forces,
|
182
|
+
imd_u.trajectory[i - first_frame].forces,
|
183
|
+
atol=1e-03,
|
184
|
+
)
|
211
185
|
|
212
186
|
def test_continue_after_disconnect(
|
213
187
|
self, docker_client, topol, tmp_path, port
|
214
188
|
):
|
215
|
-
|
216
|
-
|
217
|
-
f"imd://localhost:{port}",
|
218
|
-
continue_after_disconnect=True,
|
189
|
+
n_atoms = mda.Universe(
|
190
|
+
tmp_path / topol,
|
219
191
|
# Make sure LAMMPS topol can be read
|
220
192
|
# Does nothing if not LAMMPS
|
221
193
|
atom_style="id type x y z",
|
194
|
+
).atoms.n_atoms
|
195
|
+
u = MinimalReader(
|
196
|
+
f"imd://localhost:{port}",
|
197
|
+
n_atoms=n_atoms,
|
198
|
+
continue_after_disconnect=True,
|
222
199
|
)
|
223
200
|
# Though we disconnect here, the simulation should continue
|
224
|
-
u.
|
201
|
+
u.close()
|
225
202
|
# Wait for the simulation to finish running
|
226
203
|
time.sleep(45)
|
227
204
|
|
228
205
|
# Now, attempt to reconnect- should fail,
|
229
206
|
# since the simulation should have continued
|
230
207
|
with pytest.raises(IOError):
|
231
|
-
|
232
|
-
|
233
|
-
f"imd://localhost:{port}",
|
208
|
+
n_atoms = mda.Universe(
|
209
|
+
tmp_path / topol,
|
234
210
|
atom_style="id type x y z",
|
235
|
-
)
|
211
|
+
).atoms.n_atoms
|
212
|
+
u = MinimalReader(f"imd://localhost:{port}", n_atoms=n_atoms)
|
236
213
|
|
237
214
|
def test_wait_after_disconnect(self, docker_client, topol, tmp_path, port):
|
238
|
-
|
239
|
-
|
240
|
-
f"imd://localhost:{port}",
|
241
|
-
# Could also use None here- just being explicit
|
242
|
-
continue_after_disconnect=False,
|
215
|
+
n_atoms = mda.Universe(
|
216
|
+
tmp_path / topol,
|
243
217
|
# Make sure LAMMPS topol can be read
|
244
218
|
# Does nothing if not LAMMPS
|
245
219
|
atom_style="id type x y z",
|
220
|
+
).atoms.n_atoms
|
221
|
+
u = MinimalReader(
|
222
|
+
f"imd://localhost:{port}",
|
223
|
+
n_atoms=n_atoms,
|
224
|
+
continue_after_disconnect=False,
|
246
225
|
)
|
247
|
-
u.
|
226
|
+
u.close()
|
248
227
|
# Give the simulation engine
|
249
228
|
# enough time to finish running (though it shouldn't)
|
250
229
|
time.sleep(45)
|
251
230
|
|
252
|
-
|
253
|
-
|
254
|
-
f"imd://localhost:{port}",
|
231
|
+
n_atoms = mda.Universe(
|
232
|
+
tmp_path / topol,
|
255
233
|
atom_style="id type x y z",
|
256
|
-
)
|
234
|
+
).atoms.n_atoms
|
235
|
+
u = MinimalReader(f"imd://localhost:{port}", n_atoms=n_atoms)
|
imdclient/tests/datafiles.py
CHANGED
@@ -5,7 +5,7 @@ Ensure [docker](https://www.docker.com/) and the [NVIDIA container toolkit](http
|
|
5
5
|
|
6
6
|
To run the container:
|
7
7
|
```bash
|
8
|
-
docker pull ghcr.io/becksteinlab/streaming-md-docker:main-
|
8
|
+
docker pull ghcr.io/becksteinlab/streaming-md-docker:main-common-gpu
|
9
9
|
|
10
10
|
docker run -v $PWD/imdclient/data:/home/conda:rw -it --runtime=nvidia --gpus=all \
|
11
11
|
ghcr.io/becksteinlab/streaming-md-docker:main-Common-GPU
|
@@ -40,7 +40,7 @@ Or, for MPI builds,
|
|
40
40
|
To validate against your own simulation files, see `validate_lmp.sh` for
|
41
41
|
command line arguments.
|
42
42
|
|
43
|
-
### Compiling on ASU's Sol supercomputer
|
43
|
+
### Compiling on ASU's Sol supercomputer with MPI and GPU support
|
44
44
|
|
45
45
|
Allocate a GPU node on SOL and clone in https://github.com/ljwoods2/lammps/tree/imd-v3
|
46
46
|
|
@@ -57,6 +57,6 @@ module load openmpi/4.1.5
|
|
57
57
|
mkdir -p build_gpu
|
58
58
|
cd build_gpu
|
59
59
|
|
60
|
-
cmake ../cmake/ -D PKG_MISC=yes -D PKG_GPU=on -D GPU_API=cuda -D PKG_H5MD=yes -D BUILD_MPI=yes -
|
60
|
+
cmake ../cmake/ -D PKG_MISC=yes -D PKG_GPU=on -D GPU_API=cuda -D PKG_H5MD=yes -D BUILD_MPI=yes -DCMAKE_CXX_FLAGS="-DLAMMPS_ASYNC_IMD"
|
61
61
|
make -j 4
|
62
62
|
```
|
@@ -35,39 +35,113 @@ command line arguments.
|
|
35
35
|
|
36
36
|
### Compiling on ASU's Sol supercomputer
|
37
37
|
|
38
|
-
Allocate
|
38
|
+
Allocate requisite resources (CPU cores, nodes, GPUs) on SOL and clone in https://gitlab.com/tcbgUIUC/namd.git
|
39
39
|
|
40
|
-
After cloning, do:
|
40
|
+
After cloning and `cd`-ing to `namd` folder if you're not already there, do:
|
41
41
|
|
42
42
|
```bash
|
43
43
|
git checkout feature_imdv3
|
44
|
-
|
45
|
-
module load gcc-10.3.0-gcc-11.2.0
|
46
|
-
module load cuda-11.7.0-gcc-11.2.0
|
47
|
-
module load openmpi/4.1.5
|
44
|
+
```
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
46
|
+
Download and install TCL and FFTW libraries:
|
47
|
+
```bash
|
48
|
+
wget http://www.ks.uiuc.edu/Research/namd/libraries/fftw-linux-x86_64.tar.gz
|
49
|
+
tar xzf fftw-linux-x86_64.tar.gz
|
50
|
+
mv linux-x86_64 fftw
|
51
|
+
wget http://www.ks.uiuc.edu/Research/namd/libraries/tcl8.6.13-linux-x86_64.tar.gz
|
52
|
+
wget http://www.ks.uiuc.edu/Research/namd/libraries/tcl8.6.13-linux-x86_64-threaded.tar.gz
|
53
|
+
tar xzf tcl8.6.13-linux-x86_64.tar.gz
|
54
|
+
tar xzf tcl8.6.13-linux-x86_64-threaded.tar.gz
|
55
|
+
mv tcl8.6.13-linux-x86_64 tcl
|
56
|
+
mv tcl8.6.13-linux-x86_64-threaded tcl-threaded
|
57
|
+
```
|
58
58
|
|
59
|
+
Once can then download and unpack the Charm++ source code:
|
60
|
+
|
61
|
+
```bash
|
59
62
|
wget https://github.com/charmplusplus/charm/archive/refs/tags/v8.0.0.tar.gz
|
60
63
|
tar xf v8.0.0.tar.gz
|
64
|
+
```
|
65
|
+
|
66
|
+
Then, NAMD can be built with the following options:
|
67
|
+
|
68
|
+
#### Muticore version
|
69
|
+
|
70
|
+
```bash
|
71
|
+
module load gcc-11.2.0-gcc-11.2.0
|
61
72
|
|
62
73
|
cd charm-8.0.0
|
63
74
|
./build charm++ multicore-linux-x86_64 --with-production
|
64
|
-
cd multicore-linux-x86_64/tests/charm++/megatest
|
65
|
-
make -j 4
|
66
|
-
./megatest +p4
|
67
75
|
cd ../../../../..
|
68
76
|
|
69
77
|
./config Linux-x86_64-g++ --charm-arch multicore-linux-x86_64
|
70
78
|
|
71
79
|
cd Linux-x86_64-g++
|
72
|
-
make
|
80
|
+
make
|
81
|
+
```
|
82
|
+
|
83
|
+
#### InfiniBand UCX OpenMPI PMIx version
|
84
|
+
|
85
|
+
```bash
|
86
|
+
module load gcc-11.2.0-gcc-11.2.0
|
87
|
+
module load openmpi/4.1.5
|
88
|
+
module load pmix/4.1.3-slurm
|
89
|
+
|
90
|
+
export CPATH="/packages/apps/pmix/4.1.3-slurm/include:$CPATH"
|
91
|
+
export LIBRARY_PATH="/packages/apps/pmix/4.1.3-slurm/lib:$LIBRARY_PATH"
|
92
|
+
|
93
|
+
cd charm-8.0.0
|
94
|
+
./build charm++ ucx-linux-x86_64 ompipmix --with-production
|
95
|
+
cd ../../../../..
|
96
|
+
|
97
|
+
./config Linux-x86_64-g++ --charm-arch ucx-linux-x86_64-ompipmix
|
98
|
+
|
99
|
+
cd Linux-x86_64-g++
|
100
|
+
make
|
101
|
+
```
|
102
|
+
|
103
|
+
#### MPI version
|
104
|
+
|
105
|
+
```bash
|
106
|
+
module load gcc-11.2.0-gcc-11.2.0
|
107
|
+
module load mpich/4.2.2
|
108
|
+
|
109
|
+
env MPICXX=mpicxx ./build charm++ mpi-linux-x86_64 --with-production
|
110
|
+
cd ../../../../..
|
111
|
+
|
112
|
+
./config Linux-x86_64-g++ --charm-arch mpi-linux-x86_64
|
113
|
+
|
114
|
+
cd Linux-x86_64-g++
|
115
|
+
make
|
73
116
|
```
|
117
|
+
|
118
|
+
#### GPU-resident CUDA multicore version
|
119
|
+
|
120
|
+
```bash
|
121
|
+
module load gcc-11.2.0-gcc-11.2.0
|
122
|
+
module load mpich/4.2.2
|
123
|
+
module load cuda-11.8.0-gcc-11.2.0
|
124
|
+
module load gsl-2.7.1-gcc-11.2.0
|
125
|
+
|
126
|
+
cd charm-8.0.0
|
127
|
+
./build charm++ multicore-linux-x86_64 --with-production
|
128
|
+
cd ../../../../..
|
129
|
+
|
130
|
+
./config Linux-x86_64-g++ --charm-arch multicore-linux-x86_64 --with-single-node-cuda
|
131
|
+
|
132
|
+
cd Linux-x86_64-g++
|
133
|
+
make
|
134
|
+
```
|
135
|
+
|
136
|
+
#### GPU-resident CUDA MPI version
|
137
|
+
|
138
|
+
```bash
|
139
|
+
cd charm-8.0.0
|
140
|
+
env MPICXX=mpicxx ./build charm++ mpi-linux-x86_64-smp --with-production
|
141
|
+
cd
|
142
|
+
|
143
|
+
./config Linux-x86_64-g++ --charm-arch mpi-linux-x86_64-smp --with-single-node-cuda
|
144
|
+
|
145
|
+
cd Linux-x86_64-g++
|
146
|
+
make
|
147
|
+
```
|
@@ -0,0 +1,86 @@
|
|
1
|
+
import logging
|
2
|
+
import copy
|
3
|
+
|
4
|
+
from MDAnalysis.coordinates import core
|
5
|
+
|
6
|
+
from imdclient.IMDClient import IMDClient
|
7
|
+
from imdclient.utils import parse_host_port
|
8
|
+
|
9
|
+
logger = logging.getLogger("imdclient.IMDClient")
|
10
|
+
|
11
|
+
|
12
|
+
class MinimalReader:
|
13
|
+
"""
|
14
|
+
Minimal reader for testing purposes
|
15
|
+
|
16
|
+
Parameters
|
17
|
+
----------
|
18
|
+
filename : str
|
19
|
+
a string of the form "host:port" where host is the hostname
|
20
|
+
or IP address of the listening MD engine server and port
|
21
|
+
is the port number.
|
22
|
+
n_atoms : int
|
23
|
+
number of atoms in the system. defaults to number of atoms
|
24
|
+
in the topology. don't set this unless you know what you're doing
|
25
|
+
process_stream : bool (optional)
|
26
|
+
if True, the reader will process the stream of frames and
|
27
|
+
store them in the `trajectory` attribute. defaults to False.
|
28
|
+
kwargs : dict (optional)
|
29
|
+
keyword arguments passed to the constructed :class:`IMDClient`
|
30
|
+
"""
|
31
|
+
|
32
|
+
def __init__(self, filename, n_atoms, process_stream=False, **kwargs):
|
33
|
+
|
34
|
+
self.imd_frame = None
|
35
|
+
|
36
|
+
# a trajectory of imd frames
|
37
|
+
self.trajectory = []
|
38
|
+
|
39
|
+
self.n_atoms = n_atoms
|
40
|
+
|
41
|
+
host, port = parse_host_port(filename)
|
42
|
+
|
43
|
+
# This starts the simulation
|
44
|
+
self._imdclient = IMDClient(host, port, n_atoms, **kwargs)
|
45
|
+
|
46
|
+
self._frame = -1
|
47
|
+
|
48
|
+
if process_stream:
|
49
|
+
self._process_stream()
|
50
|
+
|
51
|
+
def _read_next_frame(self):
|
52
|
+
try:
|
53
|
+
imd_frame = self._imdclient.get_imdframe()
|
54
|
+
except EOFError:
|
55
|
+
raise
|
56
|
+
|
57
|
+
self._frame += 1
|
58
|
+
self.imd_frame = imd_frame
|
59
|
+
|
60
|
+
# Modify the box dimensions to be triclinic
|
61
|
+
self._modify_box_dimesions()
|
62
|
+
|
63
|
+
logger.debug(f"MinimalReader: Loaded frame {self._frame}")
|
64
|
+
|
65
|
+
return self.imd_frame
|
66
|
+
|
67
|
+
def _modify_box_dimesions(self):
|
68
|
+
self.imd_frame.dimensions = core.triclinic_box(*self.imd_frame.box)
|
69
|
+
|
70
|
+
def _process_stream(self):
|
71
|
+
# Process the stream of frames
|
72
|
+
while True:
|
73
|
+
try:
|
74
|
+
self.trajectory.append(copy.deepcopy(self._read_next_frame()))
|
75
|
+
# `.copy()` might not be required but adding it to cover any edge cases where a refernce gets passed
|
76
|
+
logger.debug(
|
77
|
+
f"MinimalReader: Added frame {self._frame} to trajectory"
|
78
|
+
)
|
79
|
+
except EOFError:
|
80
|
+
break
|
81
|
+
|
82
|
+
def close(self):
|
83
|
+
"""Gracefully shut down the reader. Stops the producer thread."""
|
84
|
+
logger.debug("MinimalReader: close() called")
|
85
|
+
if self._imdclient is not None:
|
86
|
+
self._imdclient.stop()
|
imdclient/tests/server.py
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
import socket
|
2
2
|
import struct
|
3
|
-
import numpy as np
|
4
3
|
import threading
|
5
|
-
import
|
4
|
+
import logging
|
5
|
+
|
6
|
+
import numpy as np
|
7
|
+
|
6
8
|
from imdclient.IMDProtocol import (
|
7
9
|
IMDHeaderType,
|
8
10
|
create_header_bytes,
|
9
11
|
create_energy_bytes,
|
10
12
|
IMDHEADERSIZE,
|
11
13
|
)
|
12
|
-
import logging
|
13
14
|
from imdclient.IMDClient import sock_contains_data, read_into_buf, IMDHeader
|
14
15
|
|
15
16
|
logger = logging.getLogger("imdclient.IMDClient")
|