flashmd 0.1.2__tar.gz → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flashmd
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Accelerated molecular dynamics with large-time-step predictions
5
5
  Author: flashmd developers
6
6
  License: Apache-2.0
@@ -22,8 +22,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
+ Requires-Dist: metatrain==2025.11
25
26
  Requires-Dist: ase
26
- Requires-Dist: pet-mad>=1.2.0
27
27
  Requires-Dist: huggingface_hub
28
28
  Dynamic: license-file
29
29
 
@@ -35,6 +35,8 @@ designed to learn and predict molecular dynamics trajectories using long strides
35
35
  very large time steps. Before using this method, make sure you are aware of its limitations, which are
36
36
  discussed in [this preprint](http://arxiv.org/abs/2505.19350).
37
37
 
38
+ The pre-trained models we make available are trained to reproduce ab-initio MD at the r2SCAN level of theory.
39
+
38
40
  Quickstart
39
41
  ----------
40
42
 
@@ -51,35 +53,41 @@ import ase.build
51
53
  import ase.units
52
54
  from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
53
55
  import torch
54
- from pet_mad.calculator import PETMADCalculator
56
+ from metatomic.torch.ase_calculator import MetatomicCalculator
55
57
 
56
- from flashmd import get_universal_model
58
+ from flashmd import get_pretrained
57
59
  from flashmd.ase.langevin import Langevin
58
60
 
59
61
 
62
+ # Choose your time step (go for 10-30x what you would use in normal MD for your system)
63
+ time_step = 16 # 16 fs; also available: 1, 2, 4, 8, 32, 64, 128 fs
64
+
60
65
  # Create a structure and initialize velocities
61
66
  atoms = ase.build.bulk("Al", "fcc", cubic=True)
62
67
  MaxwellBoltzmannDistribution(atoms, temperature_K=300)
63
68
 
64
69
  # Load models
65
70
  device="cuda" if torch.cuda.is_available() else "cpu"
66
- calculator = PETMADCalculator("1.0.1", device=device)
71
+ energy_model, flashmd_model = get_pretrained("pet-omatpes", time_step)
72
+
73
+ calculator = MetatomicCalculator(energy_model, device=device)
67
74
  atoms.calc = calculator
68
- model = get_universal_model(16) # 16 fs model; also available: 1, 4, 8, 32, 64 fs
69
- model = model.to(device)
70
75
 
71
76
  # Run MD
72
77
  dyn = Langevin(
73
78
  atoms=atoms,
74
- timestep=16*ase.units.fs,
79
+ timestep=time_step*ase.units.fs,
75
80
  temperature_K=300,
76
81
  time_constant=100*ase.units.fs,
77
- model=model,
82
+ model=flashmd_model,
78
83
  device=device
79
84
  )
80
85
  dyn.run(1000)
81
86
  ```
82
87
 
88
+ [The first time you use this code and call the `get_pretrained` function, the
89
+ pre-trained models will be downloaded. This might take a bit.]
90
+
83
91
  Other available integrators:
84
92
 
85
93
  ```py
@@ -91,11 +99,35 @@ Disclaimer
91
99
  ----------
92
100
 
93
101
  This is experimental software and should only be used if you know what you're doing.
94
- We recommend using the i-PI integrators for any serious work, and to perform constant
95
- pressure, NpT molecular dynamics. You can see
102
+ We recommend using the i-PI integrators for any serious work and/or if you need to perform
103
+ constant-pressure (NPT) molecular dynamics. You can see
96
104
  [this cookbook recipe](https://atomistic-cookbook.org/examples/flashmd/flashmd-demo.html)
97
105
  for a usage example.
98
106
  Given that the main issue we observe in direct MD trajectories is loss of equipartition
99
107
  of energy between different degrees of freedom, we recommend using a local Langevin
100
108
  thermostat, and to monitor the temperature of different atomic types or different
101
109
  parts of the simulated system.
110
+
111
+
112
+ Publication
113
+ -----------
114
+
115
+ If you found FlashMD useful, you can cite the corresponding article:
116
+
117
+ ```
118
+ @article{FlashMD,
119
+ title={FlashMD: long-stride, universal prediction of molecular dynamics},
120
+ author={Bigi, Filippo and Chong, Sanggyu and Kristiadi, Agustinus and Ceriotti, Michele},
121
+ journal={arXiv preprint arXiv:2505.19350},
122
+ year={2025}
123
+ }
124
+ ```
125
+
126
+ Reproducing the results in the article is supported with FlashMD v0.1.2:
127
+
128
+ ```bash
129
+ pip install flashmd==0.1.2 ase==3.24.0 pet-mad==1.4.3
130
+ ```
131
+
132
+ and using the "PET-MAD" models (PBEsol) from https://huggingface.co/lab-cosmo/flashmd.
133
+ Note that the results were obtained through the i-PI interface.
@@ -6,6 +6,8 @@ designed to learn and predict molecular dynamics trajectories using long strides
6
6
  very large time steps. Before using this method, make sure you are aware of its limitations, which are
7
7
  discussed in [this preprint](http://arxiv.org/abs/2505.19350).
8
8
 
9
+ The pre-trained models we make available are trained to reproduce ab-initio MD at the r2SCAN level of theory.
10
+
9
11
  Quickstart
10
12
  ----------
11
13
 
@@ -22,35 +24,41 @@ import ase.build
22
24
  import ase.units
23
25
  from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
24
26
  import torch
25
- from pet_mad.calculator import PETMADCalculator
27
+ from metatomic.torch.ase_calculator import MetatomicCalculator
26
28
 
27
- from flashmd import get_universal_model
29
+ from flashmd import get_pretrained
28
30
  from flashmd.ase.langevin import Langevin
29
31
 
30
32
 
33
+ # Choose your time step (go for 10-30x what you would use in normal MD for your system)
34
+ time_step = 16 # 16 fs; also available: 1, 2, 4, 8, 32, 64, 128 fs
35
+
31
36
  # Create a structure and initialize velocities
32
37
  atoms = ase.build.bulk("Al", "fcc", cubic=True)
33
38
  MaxwellBoltzmannDistribution(atoms, temperature_K=300)
34
39
 
35
40
  # Load models
36
41
  device="cuda" if torch.cuda.is_available() else "cpu"
37
- calculator = PETMADCalculator("1.0.1", device=device)
42
+ energy_model, flashmd_model = get_pretrained("pet-omatpes", time_step)
43
+
44
+ calculator = MetatomicCalculator(energy_model, device=device)
38
45
  atoms.calc = calculator
39
- model = get_universal_model(16) # 16 fs model; also available: 1, 4, 8, 32, 64 fs
40
- model = model.to(device)
41
46
 
42
47
  # Run MD
43
48
  dyn = Langevin(
44
49
  atoms=atoms,
45
- timestep=16*ase.units.fs,
50
+ timestep=time_step*ase.units.fs,
46
51
  temperature_K=300,
47
52
  time_constant=100*ase.units.fs,
48
- model=model,
53
+ model=flashmd_model,
49
54
  device=device
50
55
  )
51
56
  dyn.run(1000)
52
57
  ```
53
58
 
59
+ [The first time you use this code and call the `get_pretrained` function, the
60
+ pre-trained models will be downloaded. This might take a bit.]
61
+
54
62
  Other available integrators:
55
63
 
56
64
  ```py
@@ -62,11 +70,35 @@ Disclaimer
62
70
  ----------
63
71
 
64
72
  This is experimental software and should only be used if you know what you're doing.
65
- We recommend using the i-PI integrators for any serious work, and to perform constant
66
- pressure, NpT molecular dynamics. You can see
73
+ We recommend using the i-PI integrators for any serious work and/or if you need to perform
74
+ constant-pressure (NPT) molecular dynamics. You can see
67
75
  [this cookbook recipe](https://atomistic-cookbook.org/examples/flashmd/flashmd-demo.html)
68
76
  for a usage example.
69
77
  Given that the main issue we observe in direct MD trajectories is loss of equipartition
70
78
  of energy between different degrees of freedom, we recommend using a local Langevin
71
79
  thermostat, and to monitor the temperature of different atomic types or different
72
80
  parts of the simulated system.
81
+
82
+
83
+ Publication
84
+ -----------
85
+
86
+ If you found FlashMD useful, you can cite the corresponding article:
87
+
88
+ ```
89
+ @article{FlashMD,
90
+ title={FlashMD: long-stride, universal prediction of molecular dynamics},
91
+ author={Bigi, Filippo and Chong, Sanggyu and Kristiadi, Agustinus and Ceriotti, Michele},
92
+ journal={arXiv preprint arXiv:2505.19350},
93
+ year={2025}
94
+ }
95
+ ```
96
+
97
+ Reproducing the results in the article is supported with FlashMD v0.1.2:
98
+
99
+ ```bash
100
+ pip install flashmd==0.1.2 ase==3.24.0 pet-mad==1.4.3
101
+ ```
102
+
103
+ and using the "PET-MAD" models (PBEsol) from https://huggingface.co/lab-cosmo/flashmd.
104
+ Note that the results were obtained through the i-PI interface.
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "flashmd"
3
- version = "0.1.2"
3
+ version = "0.2.0"
4
4
  requires-python = ">=3.9"
5
5
 
6
6
  readme = "README.md"
@@ -9,8 +9,8 @@ description = "Accelerated molecular dynamics with large-time-step predictions"
9
9
  authors = [{name = "flashmd developers"}]
10
10
 
11
11
  dependencies = [
12
+ "metatrain==2025.11",
12
13
  "ase",
13
- "pet-mad>=1.2.0",
14
14
  "huggingface_hub",
15
15
  ]
16
16
 
@@ -1,4 +1,4 @@
1
- from .models import get_universal_model as get_universal_model
1
+ from .models import get_pretrained as get_pretrained
2
2
 
3
3
  import warnings
4
4
 
@@ -23,19 +23,13 @@ class VelocityVerlet(MolecularDynamics):
23
23
  ):
24
24
  super().__init__(atoms, timestep, **kwargs)
25
25
 
26
- models = model if isinstance(model, list) else [model]
27
- capabilities = models[0].capabilities()
26
+ capabilities = model.capabilities()
28
27
 
29
- base_timestep = float(models[0].module.base_time_step) * ase.units.fs
30
-
31
- n_time_steps = int(
32
- [k for k in capabilities.outputs.keys() if "mtt::delta_" in k][0].split(
33
- "_"
34
- )[1]
35
- )
36
- if n_time_steps != self.dt / base_timestep:
28
+ model_timestep = float(model.module.timestep)
29
+ if not np.allclose(model_timestep, self.dt / ase.units.fs):
37
30
  raise ValueError(
38
- f"Mismatch between timestep ({self.dt}) and model timestep ({base_timestep})."
31
+ f"Mismatch between timestep ({self.dt / ase.units.fs} fs) "
32
+ f"and model timestep ({model_timestep} fs)."
39
33
  )
40
34
 
41
35
  if device == "auto":
@@ -45,7 +39,7 @@ class VelocityVerlet(MolecularDynamics):
45
39
  self.device = torch.device(device)
46
40
  self.dtype = getattr(torch, capabilities.dtype)
47
41
 
48
- self.stepper = FlashMDStepper(models, n_time_steps, self.device)
42
+ self.stepper = FlashMDStepper(model, self.device)
49
43
  self.rescale_energy = rescale_energy
50
44
 
51
45
  def step(self):
@@ -39,7 +39,6 @@ def get_standard_vv_step(
39
39
  info("@flashmd: Old energy", verbosity.debug)
40
40
  old_energy = sim.properties("potential") + sim.properties("kinetic_md")
41
41
 
42
- print(motion.integrator.pdt, motion.integrator.qdt)
43
42
  motion.integrator.pstep(level=0)
44
43
  motion.integrator.pconstraints()
45
44
  motion.integrator.qcstep() # does two steps because qdt is halved in the i-PI integrator
@@ -60,21 +59,18 @@ def get_standard_vv_step(
60
59
  def get_flashmd_vv_step(sim, model, device, rescale_energy=True, random_rotation=False):
61
60
  capabilities = model.capabilities()
62
61
 
63
- base_timestep = float(model.module.base_time_step) * ase.units.fs
62
+ model_timestep = float(model.module.timestep)
64
63
 
65
- dt = sim.syslist[0].motion.dt * 2.4188843e-17 * ase.units.s
64
+ dt = sim.syslist[0].motion.dt * 2.4188843e-17 * ase.units.s / ase.units.fs
66
65
 
67
- n_time_steps = int(
68
- [k for k in capabilities.outputs.keys() if "mtt::delta_" in k][0].split("_")[1]
69
- )
70
- if not np.allclose(dt, n_time_steps * base_timestep):
66
+ if not np.allclose(dt, model_timestep):
71
67
  raise ValueError(
72
- f"Mismatch between timestep ({dt}) and model timestep ({base_timestep})."
68
+ f"Mismatch between timestep ({dt} fs) and model timestep ({model_timestep} fs)."
73
69
  )
74
70
 
75
71
  device = torch.device(device)
76
72
  dtype = getattr(torch, capabilities.dtype)
77
- stepper = FlashMDStepper([model], n_time_steps, device)
73
+ stepper = FlashMDStepper(model, device)
78
74
 
79
75
  def flashmd_vv(motion):
80
76
  info("@flashmd: Starting VV", verbosity.debug)
@@ -0,0 +1,61 @@
1
+ from huggingface_hub import hf_hub_download
2
+ from metatomic.torch import AtomisticModel, load_atomistic_model
3
+ import subprocess
4
+ import os
5
+ import time
6
+
7
+
8
+ AVAILABLE_MLIPS = ["pet-omatpes"]
9
+ AVAILABLE_TIME_STEPS = {
10
+ "pet-omatpes": [1, 2, 4, 8, 16, 32, 64, 128]
11
+ }
12
+
13
+
14
+ def get_pretrained(mlip: str = "pet-omatpes", time_step: int = 16) -> AtomisticModel:
15
+ if mlip not in AVAILABLE_MLIPS:
16
+ raise ValueError(
17
+ f"MLIP '{mlip}' is not available. "
18
+ f"Available MLIPs are: {', '.join(AVAILABLE_MLIPS)}."
19
+ )
20
+
21
+ if time_step not in AVAILABLE_TIME_STEPS[mlip]:
22
+ raise ValueError(
23
+ f"Pretrained FlashMD models based on the {mlip} MLIP are only available "
24
+ f"for time steps of {', '.join(map(str, AVAILABLE_TIME_STEPS[mlip]))} fs."
25
+ )
26
+
27
+ # Get checkpoints corresponding to the selected MLIP and FlashMD models
28
+ mlip_path = hf_hub_download(
29
+ repo_id="lab-cosmo/flashmd",
30
+ filename=f"mlip_{mlip}.ckpt",
31
+ cache_dir=None,
32
+ revision="main",
33
+ )
34
+ flashmd_path = hf_hub_download(
35
+ repo_id="lab-cosmo/flashmd",
36
+ filename=f"flashmd_{mlip}_{time_step}fs.ckpt",
37
+ cache_dir=None,
38
+ revision="main",
39
+ )
40
+
41
+ # Now we need to export both using metatrain. However, we don't want to do it if
42
+ # HuggingFace hasn't downloaded a new version of the files, so we only re-export
43
+ # if the files above have changed in the last 10 seconds.
44
+ reexport = False
45
+ exported_mlip_path = mlip_path.replace(".ckpt", ".pt")
46
+ exported_flashmd_path = flashmd_path.replace(".ckpt", ".pt")
47
+ if not os.path.exists(exported_mlip_path) or not os.path.exists(exported_flashmd_path):
48
+ reexport = True
49
+ mlip_mtime = os.path.getmtime(mlip_path)
50
+ flashmd_mtime = os.path.getmtime(flashmd_path)
51
+ if (time.time() - mlip_mtime < 10) or (time.time() - flashmd_mtime < 10):
52
+ reexport = True
53
+ if reexport:
54
+ subprocess.run(["mtt", "export", mlip_path, "-o", exported_mlip_path], capture_output=True)
55
+ subprocess.run(["mtt", "export", flashmd_path, "-o", exported_flashmd_path], capture_output=True)
56
+
57
+ # Load as AtomisticModel instances
58
+ mlip_model = load_atomistic_model(exported_mlip_path)
59
+ flashmd_model = load_atomistic_model(exported_flashmd_path)
60
+
61
+ return mlip_model, flashmd_model
@@ -4,42 +4,27 @@ from metatensor.torch import Labels, TensorBlock, TensorMap
4
4
  import torch
5
5
  from metatomic.torch import System
6
6
  from metatrain.utils.neighbor_lists import get_system_with_neighbor_lists
7
- from typing import List
8
7
  from metatomic.torch import AtomisticModel
9
8
 
10
9
 
11
10
  class FlashMDStepper:
12
11
  def __init__(
13
12
  self,
14
- models: List[AtomisticModel],
15
- n_time_steps: int,
13
+ model: AtomisticModel,
16
14
  device: torch.device,
17
- # q_error_threshold: float = 0.1,
18
- # p_error_threshold: float = 0.1,
19
- # energy_error_threshold: float = 0.1,
20
15
  ):
21
- self.n_time_steps = n_time_steps
22
-
23
- # internally, turn list of models into a dict and send to device
24
- self.models = {}
25
- for model in models:
26
- n_time_steps_model = int(
27
- [k for k in model.capabilities().outputs.keys() if "mtt::delta_" in k][
28
- 0
29
- ].split("_")[1]
30
- )
31
- self.models[n_time_steps_model] = model.to(device)
16
+ self.model = model.to(device)
32
17
 
33
18
  # one of these for each model:
34
19
  self.evaluation_options = ModelEvaluationOptions(
35
20
  length_unit="Angstrom",
36
21
  outputs={
37
- f"mtt::delta_{self.n_time_steps}_q": ModelOutput(per_atom=True),
38
- f"mtt::p_{self.n_time_steps}": ModelOutput(per_atom=True),
22
+ "positions": ModelOutput(per_atom=True),
23
+ "momenta": ModelOutput(per_atom=True),
39
24
  },
40
25
  )
41
26
 
42
- self.dtype = getattr(torch, self.models[n_time_steps].capabilities().dtype)
27
+ self.dtype = getattr(torch, self.model.capabilities().dtype)
43
28
  self.device = device
44
29
 
45
30
  def step(self, system: System):
@@ -49,27 +34,18 @@ class FlashMDStepper:
49
34
  raise ValueError("System dtype does not match stepper dtype.")
50
35
 
51
36
  system = get_system_with_neighbor_lists(
52
- system, self.models[self.n_time_steps].requested_neighbor_lists()
37
+ system, self.model.requested_neighbor_lists()
53
38
  )
54
39
 
55
40
  masses = system.get_data("masses").block().values
56
- model_outputs = self.models[self.n_time_steps](
41
+ model_outputs = self.model(
57
42
  [system], self.evaluation_options, check_consistency=False
58
43
  )
59
- delta_q_scaled = (
60
- model_outputs[f"mtt::delta_{self.n_time_steps}_q"]
61
- .block()
62
- .values.squeeze(-1)
63
- )
64
- p_scaled = (
65
- model_outputs[f"mtt::p_{self.n_time_steps}"].block().values.squeeze(-1)
66
- )
67
- sqrt_masses = torch.sqrt(masses)
68
- delta_q = delta_q_scaled / sqrt_masses
69
- p = p_scaled * sqrt_masses
44
+ new_q = model_outputs["positions"].block().values.squeeze(-1)
45
+ new_p = model_outputs["momenta"].block().values.squeeze(-1)
70
46
 
71
47
  new_system = System(
72
- positions=system.positions + delta_q,
48
+ positions=new_q,
73
49
  types=system.types,
74
50
  cell=system.cell,
75
51
  pbc=system.pbc,
@@ -80,7 +56,7 @@ class FlashMDStepper:
80
56
  keys=Labels.single().to(self.device),
81
57
  blocks=[
82
58
  TensorBlock(
83
- values=p.unsqueeze(-1),
59
+ values=new_p.unsqueeze(-1),
84
60
  samples=Labels(
85
61
  names=["system", "atom"],
86
62
  values=torch.tensor(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flashmd
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Accelerated molecular dynamics with large-time-step predictions
5
5
  Author: flashmd developers
6
6
  License: Apache-2.0
@@ -22,8 +22,8 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
22
  Requires-Python: >=3.9
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
+ Requires-Dist: metatrain==2025.11
25
26
  Requires-Dist: ase
26
- Requires-Dist: pet-mad>=1.2.0
27
27
  Requires-Dist: huggingface_hub
28
28
  Dynamic: license-file
29
29
 
@@ -35,6 +35,8 @@ designed to learn and predict molecular dynamics trajectories using long strides
35
35
  very large time steps. Before using this method, make sure you are aware of its limitations, which are
36
36
  discussed in [this preprint](http://arxiv.org/abs/2505.19350).
37
37
 
38
+ The pre-trained models we make available are trained to reproduce ab-initio MD at the r2SCAN level of theory.
39
+
38
40
  Quickstart
39
41
  ----------
40
42
 
@@ -51,35 +53,41 @@ import ase.build
51
53
  import ase.units
52
54
  from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
53
55
  import torch
54
- from pet_mad.calculator import PETMADCalculator
56
+ from metatomic.torch.ase_calculator import MetatomicCalculator
55
57
 
56
- from flashmd import get_universal_model
58
+ from flashmd import get_pretrained
57
59
  from flashmd.ase.langevin import Langevin
58
60
 
59
61
 
62
+ # Choose your time step (go for 10-30x what you would use in normal MD for your system)
63
+ time_step = 16 # 16 fs; also available: 1, 2, 4, 8, 32, 64, 128 fs
64
+
60
65
  # Create a structure and initialize velocities
61
66
  atoms = ase.build.bulk("Al", "fcc", cubic=True)
62
67
  MaxwellBoltzmannDistribution(atoms, temperature_K=300)
63
68
 
64
69
  # Load models
65
70
  device="cuda" if torch.cuda.is_available() else "cpu"
66
- calculator = PETMADCalculator("1.0.1", device=device)
71
+ energy_model, flashmd_model = get_pretrained("pet-omatpes", time_step)
72
+
73
+ calculator = MetatomicCalculator(energy_model, device=device)
67
74
  atoms.calc = calculator
68
- model = get_universal_model(16) # 16 fs model; also available: 1, 4, 8, 32, 64 fs
69
- model = model.to(device)
70
75
 
71
76
  # Run MD
72
77
  dyn = Langevin(
73
78
  atoms=atoms,
74
- timestep=16*ase.units.fs,
79
+ timestep=time_step*ase.units.fs,
75
80
  temperature_K=300,
76
81
  time_constant=100*ase.units.fs,
77
- model=model,
82
+ model=flashmd_model,
78
83
  device=device
79
84
  )
80
85
  dyn.run(1000)
81
86
  ```
82
87
 
88
+ [The first time you use this code and call the `get_pretrained` function, the
89
+ pre-trained models will be downloaded. This might take a bit.]
90
+
83
91
  Other available integrators:
84
92
 
85
93
  ```py
@@ -91,11 +99,35 @@ Disclaimer
91
99
  ----------
92
100
 
93
101
  This is experimental software and should only be used if you know what you're doing.
94
- We recommend using the i-PI integrators for any serious work, and to perform constant
95
- pressure, NpT molecular dynamics. You can see
102
+ We recommend using the i-PI integrators for any serious work and/or if you need to perform
103
+ constant-pressure (NPT) molecular dynamics. You can see
96
104
  [this cookbook recipe](https://atomistic-cookbook.org/examples/flashmd/flashmd-demo.html)
97
105
  for a usage example.
98
106
  Given that the main issue we observe in direct MD trajectories is loss of equipartition
99
107
  of energy between different degrees of freedom, we recommend using a local Langevin
100
108
  thermostat, and to monitor the temperature of different atomic types or different
101
109
  parts of the simulated system.
110
+
111
+
112
+ Publication
113
+ -----------
114
+
115
+ If you found FlashMD useful, you can cite the corresponding article:
116
+
117
+ ```
118
+ @article{FlashMD,
119
+ title={FlashMD: long-stride, universal prediction of molecular dynamics},
120
+ author={Bigi, Filippo and Chong, Sanggyu and Kristiadi, Agustinus and Ceriotti, Michele},
121
+ journal={arXiv preprint arXiv:2505.19350},
122
+ year={2025}
123
+ }
124
+ ```
125
+
126
+ Reproducing the results in the article is supported with FlashMD v0.1.2:
127
+
128
+ ```bash
129
+ pip install flashmd==0.1.2 ase==3.24.0 pet-mad==1.4.3
130
+ ```
131
+
132
+ and using the "PET-MAD" models (PBEsol) from https://huggingface.co/lab-cosmo/flashmd.
133
+ Note that the results were obtained through the i-PI interface.
@@ -1,3 +1,3 @@
1
+ metatrain==2025.11
1
2
  ase
2
- pet-mad>=1.2.0
3
3
  huggingface_hub
@@ -1,18 +0,0 @@
1
- from huggingface_hub import hf_hub_download
2
- from metatomic.torch import AtomisticModel, load_atomistic_model
3
-
4
-
5
- def get_universal_model(time_step: int = 16) -> AtomisticModel:
6
- if time_step not in [1, 4, 8, 16, 32, 64]:
7
- raise ValueError(
8
- "Universal FlashMD models are only available for"
9
- " time steps of 1, 4, 8, 16, 32, 64 fs."
10
- )
11
-
12
- model_path = hf_hub_download(
13
- repo_id="lab-cosmo/flashmd",
14
- filename=f"flashmd_{time_step}fs.pt",
15
- cache_dir=None,
16
- revision="main",
17
- )
18
- return load_atomistic_model(model_path)
File without changes
File without changes
File without changes