Skip to content

NVT Nosé Hoover does not work for chain_length=1 #266

@thomasloux

Description

@thomasloux

The thermostat fails when running half_step_chain_fn:

scale = torch.exp(-delta_8 * p_xi[1] / Q[1]) # Around line 403 in md.py

The patch is easy probably, for instance by comparing with ASE implementation (mostly the same but slightly better for edge cases like this one): https://ase-lib.org/_modules/ase/md/nose_hoover_chain.html in NoseHooverChainThermostat._integrate_p_eta_j

Code to reproduce:

"""NVT simulation with MACE and Nose-Hoover thermostat."""

import os

import torch
from ase.build import bulk

import torch_sim as ts
from torch_sim.integrators.nvt_batched import nvt_nose_hoover as nvt_nose_hoover_batched
from torch_sim.integrators.nvt_batched import nvt_nose_hoover_invariant as nvt_nose_hoover_invariant_batched
# from torch_sim.integrators.nvt import nvt_nose_hoover, nvt_nose_hoover_invariant
from orb_models.forcefield import pretrained

from torch_sim.models.orb import OrbModel
from torch_sim.quantities import calc_kT
from torch_sim.units import MetalUnits as Units
from torch_sim.state import concatenate_states
from torch_sim.state import initialize_state
from torch_sim.integrators.md import calculate_momenta
from torch_sim.quantities import calc_kinetic_energy


# Set device and data type
device = "cuda" if torch.cuda.is_available() else "cpu"
# device = torch.device("cpu")
# dtype = torch.float32


# Number of steps to run
N_steps = 100

# Create diamond cubic Silicon
si_dc = bulk("Si", "diamond", a=5.43, cubic=True)

orbff = pretrained.orb_v3_conservative_inf_omat(
        device=device,
        # precision="float32-highest",
        precision="float64",
        compile=False
    )
dtype = torch.get_default_dtype()
orb_model = OrbModel(model=orbff, dtype=torch.get_default_dtype(), device=device)

dt = 0.001 * Units.time  # Timestep (ps)
kT = (
    torch.tensor(1000, device=device, dtype=dtype) * Units.temperature
)  # Initial temperature (K)


# state = ts.io.atoms_to_state(si_dc, device=device, dtype=dtype)
state = initialize_state(si_dc, device=device, dtype=dtype)

# Run initial inference
results = orb_model(state)



nvt_init, nvt_update = nvt_nose_hoover_batched(model=orb_model, kT=kT, dt=dt, chain_length=1)
state = nvt_init(state=state, kT=kT, seed=1)

for step in range(N_steps):
    if step % 10 == 0:
        temp = (
            calc_kT(
                masses=state.masses, momenta=state.momenta, system_idx=state.system_idx
            )
            / Units.temperature
        )
        invariant = nvt_nose_hoover_invariant_batched(state, kT=kT)
        print(f"{step}: Temperature: {temp}: {invariant}")
    state = nvt_update(state=state, kT=kT)

final_temp = (
    calc_kT(masses=state.masses, momenta=state.momenta, system_idx=state.system_idx)
    / Units.temperature
)
print(f"Final temperature: {final_temp}")

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions