Git Product home page Git Product logo

cedergrouphub / chgnet Goto Github PK

View Code? Open in Web Editor NEW
220.0 5.0 60.0 13.51 MB

Pretrained universal neural network potential for charge-informed atomistic modeling https://chgnet.lbl.gov

Home Page: https://doi.org/10.1038/s42256-023-00716-3

License: Other

Python 72.98% CSS 1.30% HTML 0.42% Svelte 0.96% TypeScript 0.16% JavaScript 0.47% Cython 1.37% C 22.34%
atomistic-simulations charge-distribution charge-transport computational-materials-science force-fields graph-neural-networks machine-learning

chgnet's Introduction

CHGNet

Tests Codacy Badge arXiv GitHub repo size PyPI Docs Requires Python 3.9+

A pretrained universal neural network potential for charge-informed atomistic modeling (see publication) Logo Crystal Hamiltonian Graph neural Network is pretrained on the GGA/GGA+U static and relaxation trajectories from Materials Project, a comprehensive dataset consisting of more than 1.5 Million structures from 146k compounds spanning the whole periodic table.

CHGNet highlights its ability to study electron interactions and charge distribution in atomistic modeling with near DFT accuracy. The charge inference is realized by regularizing the atom features with DFT magnetic moments, which carry rich information about both local ionic environments and charge distribution.

Pretrained CHGNet achieves excellent performance on materials stability prediction from unrelaxed structures according to Matbench Discovery [repo].

Example notebooks

Notebooks Google Colab Descriptions
CHGNet Basics Open in Google Colab Examples for loading pre-trained CHGNet, predicting energy, force, stress, magmom as well as running structure optimization and MD.
Tuning CHGNet Open in Google Colab Examples of fine tuning the pretrained CHGNet to your system of interest.
Visualize Relaxation Open in Google Colab Crystal Toolkit app that visualizes convergence of atom positions, energies and forces of a structure during CHGNet relaxation.
Phonon DOS + Bands Open in Google Colab Use CHGNet with the atomate2 phonon workflow based on finite displacements as implemented in Phonopy to calculate phonon density of states and band structure for Si (mp-149).
Elastic tensor + bulk/shear modulus Open in Google Colab Use CHGNet with the atomate2 elastic workflow based on a stress-strain approach to calculate elastic tensor and derived bulk and shear modulus for Si (mp-149).

Installation

pip install chgnet

if PyPI installation fails or you need the latest main branch commits, you can install from source:

pip install git+https://github.com/CederGroupHub/chgnet

Tutorials and Docs

2023-11-02-sciML-webinar

See the sciML webinar tutorial on 2023-11-02 and API docs.

Usage

Direct Inference (Static Calculation)

Pretrained CHGNet can predict the energy (eV/atom), force (eV/A), stress (GPa) and magmom ($\mu_B$) of a given structure.

from chgnet.model.model import CHGNet
from pymatgen.core import Structure

chgnet = CHGNet.load()
structure = Structure.from_file('examples/mp-18767-LiMnO2.cif')
prediction = chgnet.predict_structure(structure)

for key, unit in [
    ("energy", "eV/atom"),
    ("forces", "eV/A"),
    ("stress", "GPa"),
    ("magmom", "mu_B"),
]:
    print(f"CHGNet-predicted {key} ({unit}):\n{prediction[key[0]]}\n")

Molecular Dynamics

Charge-informed molecular dynamics can be simulated with pretrained CHGNet through ASE python interface (see below), or through LAMMPS.

from chgnet.model.model import CHGNet
from chgnet.model.dynamics import MolecularDynamics
from pymatgen.core import Structure
import warnings
warnings.filterwarnings("ignore", module="pymatgen")
warnings.filterwarnings("ignore", module="ase")

structure = Structure.from_file("examples/mp-18767-LiMnO2.cif")
chgnet = CHGNet.load()

md = MolecularDynamics(
    atoms=structure,
    model=chgnet,
    ensemble="nvt",
    temperature=1000,  # in K
    timestep=2,  # in femto-seconds
    trajectory="md_out.traj",
    logfile="md_out.log",
    loginterval=100,
)
md.run(50)  # run a 0.1 ps MD simulation

The MD defaults to CUDA if available, to manually set device to cpu or mps: MolecularDynamics(use_device='cpu').

MD outputs are saved to the ASE trajectory file, to visualize the MD trajectory and magnetic moments after the MD run:

from ase.io.trajectory import Trajectory
from pymatgen.io.ase import AseAtomsAdaptor
from chgnet.utils import solve_charge_by_mag

traj = Trajectory("md_out.traj")
mag = traj[-1].get_magnetic_moments()

# get the non-charge-decorated structure
structure = AseAtomsAdaptor.get_structure(traj[-1])
print(structure)

# get the charge-decorated structure
struct_with_chg = solve_charge_by_mag(structure)
print(struct_with_chg)

To manipulate the MD trajectory, convert to other data formats, calculate mean square displacement, etc, please refer to ASE trajectory documentation.

Structure Optimization

CHGNet can perform fast structure optimization and provide site-wise magnetic moments. This makes it ideal for pre-relaxation and MAGMOM initialization in spin-polarized DFT.

from chgnet.model import StructOptimizer

relaxer = StructOptimizer()
result = relaxer.relax(structure)
print("CHGNet relaxed structure", result["final_structure"])
print("relaxed total energy in eV:", result['trajectory'].energies[-1])

Available Weights

CHGNet 0.3.0 is released with new pretrained weights! (release date: 10/22/23)

CHGNet.load() now loads 0.3.0 by default, previous 0.2.0 version can be loaded with CHGNet.load('0.2.0')

Model Training / Fine-tune

Fine-tuning will help achieve better accuracy if a high-precision study is desired. To train/tune a CHGNet, you need to define your data in a pytorch Dataset object. The example datasets are provided in data/dataset.py

from chgnet.data.dataset import StructureData, get_train_val_test_loader
from chgnet.trainer import Trainer

dataset = StructureData(
    structures=list_of_structures,
    energies=list_of_energies,
    forces=list_of_forces,
    stresses=list_of_stresses,
    magmoms=list_of_magmoms,
)
train_loader, val_loader, test_loader = get_train_val_test_loader(
    dataset, batch_size=32, train_ratio=0.9, val_ratio=0.05
)
trainer = Trainer(
    model=chgnet,
    targets="efsm",
    optimizer="Adam",
    criterion="MSE",
    learning_rate=1e-2,
    epochs=50,
    use_device="cuda",
)

trainer.train(train_loader, val_loader, test_loader)

Notes for Training

Check fine-tuning example notebook

  1. The target quantity used for training should be energy/atom (not total energy) if you're fine-tuning the pretrained CHGNet.
  2. The pretrained dataset of CHGNet comes from GGA+U DFT with MaterialsProject2020Compatibility corrections applied. The parameter for VASP is described in MPRelaxSet. If you're fine-tuning with MPRelaxSet, it is recommended to apply the MP2020 compatibility to your energy labels so that they're consistent with the pretrained dataset.
  3. If you're fine-tuning to functionals other than GGA, we recommend you refit the AtomRef.
  4. CHGNet stress is in units of GPa, and the unit conversion has already been included in dataset.py. So VASP stress can be directly fed to StructureData
  5. To save time from graph conversion step for each training, we recommend you use GraphData defined in dataset.py, which reads graphs directly from saved directory. To create saved graphs, see examples/make_graphs.py.

MPtrj Dataset

The Materials Project trajectory (MPtrj) dataset used to pretrain CHGNet is available at figshare.

The MPtrj dataset consists of all the GGA/GGA+U DFT calculations from the September 2022 Materials Project. By using the MPtrj dataset, users agree to abide the Materials Project terms of use.

Reference

If you use CHGNet or MPtrj dataset, please cite this paper:

@article{deng_2023_chgnet,
    title={CHGNet as a pretrained universal neural network potential for charge-informed atomistic modelling},
    DOI={10.1038/s42256-023-00716-3},
    journal={Nature Machine Intelligence},
    author={Deng, Bowen and Zhong, Peichen and Jun, KyuJung and Riebesell, Janosh and Han, Kevin and Bartel, Christopher J. and Ceder, Gerbrand},
    year={2023},
    pages={1–11}
}

Development & Bugs

CHGNet is under active development, if you encounter any bugs in installation and usage, please open an issue. We appreciate your contributions!

chgnet's People

Contributors

aegisik avatar andrew-s-rosen avatar bowend-ucb avatar janosh avatar lbluque avatar tsihyoung avatar zhongpc avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

chgnet's Issues

[Feature Request]: How to get the relaxed structure

Email (Optional)

[email protected]

Problem

structure.perturb(0.1)
result = relaxer.relax(structure, verbose=False)
print(f"\nCHGNet took {len(result['trajectory'])} steps. Relaxed structure:")
print(result["final_structure"])

How to get the relaxed structure, the error of 30mev/atom in the article, is it relaxed?

Proposed Solution

Hope to get the final structure of cif.

Alternatives

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

[FineTuning]

Hello everyone,

I have a question regarding the fine-tuning process of CHGNet.

If I retrain CHGNet using energy, force, and stress data, will the model still utilize the magmom (magnetic moments) after the retraining process?

I would appreciate your insights on this matter.

Thank you and have a nice day!

[Bug]: file not found

Email (Optional)

[email protected]

Version

v.0.3.8

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Dear developers of CHGNet,

We are trying to develop the interface of LAMMPS for CHGNet by this link CHGNet: https://github.com/advancesoftcorp/lammps/tree/based-on-lammps_2Jun2022/src/ML-CHGNET
But this link is not working and showing "page not found".

So, kindly resolve the issue.
It would be great that it will interest you.

Best Regards,
Anurag Kumar
Indian Institute of Technology, Roorkee
India

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Bug in crystaltoolkit_relax_viewer.ipynb in examples

Hi,

I tried to run crystaltoolkit_relax_viewer.ipynb in the "examples" folder, but running the last cell gives this error:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[11], line 17
     11 if "struct_layout" not in vars():
     12     # don't create layout twice because it causes duplicate
     13     # ID errors when restarting Dash app in Jupyter notebook
     14     struct_comp = ctc.StructureMoleculeComponent(
     15         id="structure", struct_or_mol=structure
     16     )
---> 17     struct_layout = struct_comp.layout()
     20 step_size = max(1, len(trajectory) // 20)  # ensure slider has max 20 steps
     21 slider = dcc.Slider(
     22     id="slider", min=0, max=len(trajectory) - 1, step=step_size, updatemode="drag"
     23 )

File ~/miniconda3/envs/chem/lib/python3.9/site-packages/crystal_toolkit/components/structure.py:896, in StructureMoleculeComponent.layout(self, size)
    886 def layout(self, size: str = "500px") -> html.Div:
    887     """Get the layout for this component.
    888 
    889     Args:
   (...)
    893         html.Div: A html.Div containing the 3D structure or molecule
    894     """
    895     return html.Div(
--> 896         self._sub_layouts["struct"], style={"width": size, "height": size}
    897     )

File ~/miniconda3/envs/chem/lib/python3.9/site-packages/crystal_toolkit/components/structure.py:851, in StructureMoleculeComponent._sub_layouts(self)
    847     options_layout = None
    849 if self.show_legend:
    850     legend_layout = html.Div(
--> 851         self._make_legend(self._initial_data["legend_data"]),
    852         id=self.id("legend_container"),
    853     )
    854 else:
    855     legend_layout = None

File ~/miniconda3/envs/chem/lib/python3.9/site-packages/crystal_toolkit/components/structure.py:592, in StructureMoleculeComponent._make_legend(self, legend)
    585     c = tuple(int(hex_code[1:][i : i + 2], 16) for i in (0, 2, 4))
    586     return (
    587         "black"
    588         if 1 - (c[0] * 0.299 + c[1] * 0.587 + c[2] * 0.114) / 255 < 0.5
    589         else "white"
    590     )
--> 592 legend_colors = {
    593     k: self._legend.get_color(Species(k))
    594     for k, v in legend["composition"].items()
    595 }
    597 legend_elements = [
    598     html.Span(
    599         html.Span(
   (...)
    605     for name, color in legend_colors.items()
    606 ]
    608 return html.Div(
    609     legend_elements,
    610     id=self.id("legend"),
    611     style={"display": "flex"},
    612     className="buttons",
    613 )

File ~/miniconda3/envs/chem/lib/python3.9/site-packages/crystal_toolkit/components/structure.py:593, in <dictcomp>(.0)
    585     c = tuple(int(hex_code[1:][i : i + 2], 16) for i in (0, 2, 4))
    586     return (
    587         "black"
    588         if 1 - (c[0] * 0.299 + c[1] * 0.587 + c[2] * 0.114) / 255 < 0.5
    589         else "white"
    590     )
    592 legend_colors = {
--> 593     k: self._legend.get_color(Species(k))
    594     for k, v in legend["composition"].items()
    595 }
    597 legend_elements = [
    598     html.Span(
    599         html.Span(
   (...)
    605     for name, color in legend_colors.items()
    606 ]
    608 return html.Div(
    609     legend_elements,
    610     id=self.id("legend"),
    611     style={"display": "flex"},
    612     className="buttons",
    613 )

File ~/miniconda3/envs/chem/lib/python3.9/site-packages/pymatgen/core/periodic_table.py:1077, in Species.__init__(self, symbol, oxidation_state, properties)
   1049 def __init__(
   1050     self,
   1051     symbol: str,
   1052     oxidation_state: float | None = 0.0,
   1053     properties: dict | None = None,
   1054 ):
   1055     """
   1056     Initializes a Species.
   1057 
   (...)
   1075         Properties are now checked when comparing two Species for equality.
   1076     """
-> 1077     self._el = Element(symbol)
   1078     self._oxi_state = oxidation_state
   1079     self._properties = properties or {}

File ~/miniconda3/envs/chem/lib/python3.9/enum.py:384, in EnumMeta.__call__(cls, value, names, module, qualname, type, start)
    359 """
    360 Either returns an existing member, or creates a new enum class.
    361 
   (...)
    381 `type`, if set, will be mixed in as the first base class.
    382 """
    383 if names is None:  # simple value lookup
--> 384     return cls.__new__(cls, value)
    385 # otherwise, functional API: we're creating a new Enum type
    386 return cls._create_(
    387         value,
    388         names,
   (...)
    392         start=start,
    393         )

File ~/miniconda3/envs/chem/lib/python3.9/enum.py:702, in Enum.__new__(cls, value)
    700 ve_exc = ValueError("%r is not a valid %s" % (value, cls.__qualname__))
    701 if result is None and exc is None:
--> 702     raise ve_exc
    703 elif exc is None:
    704     exc = TypeError(
    705             'error in %s._missing_: returned %r instead of None or a valid member'
    706             % (cls.__name__, result)
    707             )

ValueError: 'Li+' is not a valid Element

I think it is related to the presence of oxidation state in the cif file. Is this the expected behavior? If not, how should it be fixed?

Thanks,
JW

[Bug]: Error Encountered when Using 'predict_structure' for Structure Prediction

Email (Optional)

No response

Version

tried both v0.2.0 and v0.3.0 versions

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I encountered the following error when using the 'predict_structure' function to feed the structure, like this: 'prediction = chgnet.predict_structure(structure, return_crystal_feas=True)

image

structure:
image

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

unexpected relaxation steps

I encountered an unexpected situation.

I am trying to use CHGNET for static calculations and compare the energy with DFT values. However, when I set steps=0, the relaxation process continues indefinitely, without being limited by the default 500 steps:

from chgnet.model import StructOptimizer

traj = StructOptimizer().relax(s, steps=0)

This behavior is not what I was expecting.

I wonder if this is intentional.

When I set steps = 1, the output appears as follows:

CrystalGraphConverter initialized with atom_cutoff5, bond_cutoff3
CHGNet initialized with 400438 Parameters, is_intensive=True
      Step     Time          Energy         fmax
*Force-consistent energies used in optimization.
FIRE:    0 21:32:17     -326.627214*       4.2172
FIRE:    1 21:32:17     -324.937722*      45.8358

This output is as expected.

[Bug]: vasp_utils.py , parse_vasp_dir function gives me error when parsing file.

Email (Optional)

[email protected]

Version

0.3.5

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

  1. I am attempting to run the parse_vasp_dir function, I have a directory that contains all of the necessary files, I know they are fully converged. Here are the files I'm attempting to run, I removed the wavefunction and charge files because of size.
    test.zip

Code snippet

# ./my_vasp_calc_dir contains vasprun.xml OSZICAR etc.
dataset_dict = parse_vasp_dir(file_root="/home/USER/NbOC/test")
print(list(dataset_dict))

Log output

RuntimeError                              Traceback (most recent call last)
Cell In[2], line 4
      1 from chgnet.utils import parse_vasp_dir
      3 # ./my_vasp_calc_dir contains vasprun.xml OSZICAR etc.
----> 4 dataset_dict = parse_vasp_dir(file_root="/home/nacho/NbOC/test")
      5 print(list(dataset_dict))

File ~\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\chgnet\utils\vasp_utils.py:151, in parse_vasp_dir(file_root, check_electronic_convergence)
    148         dataset["stress"].append(ionic_step["stress"])
    150 if dataset["uncorrected_total_energy"] == []:
--> 151     raise RuntimeError(f"No data parsed from {file_root}!")
    153 return dataset

RuntimeError: No data parsed from /home/USER/NbOC/test!

Code of Conduct

  • I agree to follow this project's Code of Conduct

units and format when compared with trajectories (ASE)

Just going on the README.md, the units and shapes of results from prediction = chgnet.predict_structure(structure) and relaxer = StructOptimizer(); result = relaxer.relax(structure) are different. Energies is easily fixed by multiplying by number of atoms, but the other quantities don't seem to have such a simple relationship.

I figure that you have clear units from predict_structure, but when I look at ASE documentation, the units from their atoms object is not 100% clear to me. Furthermore, the "stresses" prediction prediction["s"] is a completely different shape from the results["trajectory"][-1]. How do I convert between them?

[Bug]: MPS out of memory error when using cpu device

Email (Optional)

No response

Version

v0.3.8

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I am attempting to run calculations, such as single point energies, using the CHGNetCalculator ASE calculator on MacOS via GitHub actions: https://github.com/stfc/janus-core/actions/runs/9943461072/job/27469030924?pr=214

However, I get a RuntimeError, which I believe is because CHGnet.load is not passed device / use_device (https://github.com/CederGroupHub/chgnet/blob/main/chgnet/model/dynamics.py#L92).

This means that within CHGnet.load, determine_device initially attempts to load the model to the "mps" device, causing an error as no MPS memory has been allocated.

Two potential solutions are checking the availability of MPS memory, or preferably passing device to CHGnet.load, reducing the need to transfer between devices unnecessarily.

Code snippet

from chgnet.model.dynamics import CHGNetCalculator
CHGNetCalculator(use_device="cpu")

Log output

tests/test_mlip_calculators.py:26: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
janus_core/helpers/mlip_calculators.py:104: in choose_calculator
    calculator = CHGNetCalculator(use_device=device, **kwargs)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/chgnet/model/dynamics.py:91: in __init__
    self.model = (model or CHGNet.load(verbose=False)).to(self.device)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/chgnet/model/model.py:722: in load
    model = model.to(device)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/torch/nn/modules/module.py:1152: in to
    return self._apply(convert)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/torch/nn/modules/module.py:802: in _apply
    module._apply(fn)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/torch/nn/modules/module.py:802: in _apply
    module._apply(fn)
../../../Library/Caches/pypoetry/virtualenvs/janus-core-2KE8lRKs-py3.11/lib/python3.11/site-packages/torch/nn/modules/module.py:825: in _apply
    param_applied = fn(param)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

t = Parameter containing:
tensor([[ -3.4431,  -0.1279,  -2.8300,  -3.4737,  -7.4946,  -8.2354,  -8.1611,
          -8.3861...          -0.3448,  -0.4364,  -0.1661,  -0.3680,  -4.1869,  -8.4233, -10.0467,
         -12.0953, -12.5228, -14.2530]])

    def convert(t):
        if convert_to_format is not None and t.dim() in (4, 5):
            return t.to(device, dtype if t.is_floating_point() or t.is_complex() else None,
                        non_blocking, memory_format=convert_to_format)
>       return t.to(device, dtype if t.is_floating_point() or t.is_complex() else None, non_blocking)
E       RuntimeError: MPS backend out of memory (MPS allocated: 0 bytes, other allocations: 0 bytes, max allowed: 7.93 GB). Tried to allocate 512 bytes on private pool. Use PYTORCH_MPS_HIGH_WATERMARK_RATIO=0.0 to disable upper limit for memory allocations (may cause system failure).

Code of Conduct

  • I agree to follow this project's Code of Conduct

Failed to use cuda

I tried running on GPU for faster structure optimization by setting use_device="cuda" in MolecularDynamics.

from chgnet.model.model import CHGNet
from chgnet.model.dynamics import MolecularDynamics
from pymatgen.core import Structure

structure = Structure.from_file("examples/o-LiMnO2_unit.cif")
chgnet = CHGNet.load()

md = MolecularDynamics(
    atoms=structure,
    model=chgnet,
    ensemble="nvt",
    compressibility_au=1.6,
    temperature=1000,  # in K
    timestep=2,  # in femto-seconds
    trajectory="md_out.traj",
    logfile="md_out.log",
    loginterval=100,
    use_device="cuda",  # use 'cuda' for faster MD
)
md.run(50)  # run a 0.1 ps MD simulation

But in the head of out put, it showed

CHGNet initialized with 400438 Parameters
CHGNet will run on cpu

Did I miss any step? Additionally, I wonder if cuda is avaliable in structure optimization.

Energy error

Email (Optional)

[email protected]

Version

0.3.0

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

The result of the test was" CHGNet predicted energy (eV/atom):-4.5642852783203125"
but ture is "-1.119ev/atom"

Code snippet

prediction = chgnet.predict_structure(structure)

for key, unit in [
    ("energy", "eV/atom"),
    ("forces", "eV/A"),
    ("stress", "GPa"),
    ("magmom", "mu_B"),
]:
    print(f"CHGNet-predicted {key} ({unit}):\n{prediction[key[0]]}\n")

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Loss spikes during training expected?

Email (Optional)

[email protected]

Version

v0.2.1

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Dear Authors,

Thank you for sharing the source code for CHGNet. I am attempting to train CHGNet from scratch using the Materials Project trajectory (MPtrj) dataset that you've provided. However, I've noticed some instability during the training process. Specifically, there are instances where the loss spikes significantly. The training process looks like this:

Epoch: [0][1/44451] | Time (1.624)(0.338) | Loss 0.3169(0.3169) | MAE e 0.403(0.403) f 0.052(0.052)
Epoch: [0][100/44451] | Time (0.623)(0.335) | Loss 0.5776(1.4586) | MAE e 0.412(0.477) f 0.139(0.206)
Epoch: [0][200/44451] | Time (0.626)(0.339) | Loss 0.4351(1.6517) | MAE e 0.399(0.458) f 0.116(0.208)
Epoch: [0][300/44451] | Time (0.892)(0.607) | Loss 0.9594(1.2858) | MAE e 0.511(0.443) f 0.238(0.192)
...
Epoch: [0][26300/44451] | Time (0.996)(0.654) | Loss 1.3189(0.6118) | MAE e 0.160(0.188) f 0.425(0.217)
Epoch: [0][26400/44451] | Time (0.995)(0.653) | Loss 0.3473(0.6110) | MAE e 0.214(0.188) f 0.263(0.217)
Epoch: [0][26500/44451] | Time (0.998)(0.655) | Loss 124.5792(1.6960) | MAE e 0.684(0.189) f 2.491(0.220)
Epoch: [0][26600/44451] | Time (0.996)(0.654) | Loss 0.6696(641.2061) | MAE e 0.470(0.191) f 0.318(0.249)
Epoch: [0][26700/44451] | Time (0.995)(0.653) | Loss 3.6322(638.8499) | MAE e 0.445(0.192) f 0.847(0.251)
Epoch: [0][26800/44451] | Time (0.998)(0.656) | Loss 6.0389(636.4801) | MAE e 0.522(0.193) f 0.643(0.252)
....
Epoch: [0][37300/44451] | Time (1.015)(0.665) | Loss 1.2740(1311.9422) | MAE e 0.544(0.279) f 0.345(0.567)
Epoch: [0][37400/44451] | Time (1.015)(0.664) | Loss 2.2951(1308.5920) | MAE e 0.447(0.280) f 0.466(0.567)
Epoch: [0][37500/44451] | Time (1.017)(0.666) | Loss 5.7568(1305.1261) | MAE e 0.596(0.280) f 0.605(0.567)
Epoch: [0][37600/44451] | Time (1.016)(0.666) | Loss 26822.4453(1302.3834) | MAE e 0.540(0.281) f 15.234(0.567)
Epoch: [0][37700/44451] | Time (1.016)(0.665) | Loss 13.8838(1299.0148) | MAE e 0.538(0.281) f 0.703(0.567)
Epoch: [0][37800/44451] | Time (1.015)(0.664) | Loss 2.9397(1295.8719) | MAE e 0.441(0.282) f 0.345(0.567)

Is this expected behavior? I would greatly appreciate it if you could provide a full demo (maybe a .py file) illustrating how to train CHGNet from scratch. I aim to compare my recently developed model with CHGNet under identical conditions. I've included a code snippet above for your reference. Thank you very much.

Code snippet

# %%
import os
os.environ['CUDA_VISIBLE_DEVICES'] = "1"
import pickle as pk
from chgnet.data.dataset import StructureData, collate_graphs, StructureJsonData
from chgnet.graph.converter import CrystalGraphConverter
from chgnet.trainer import Trainer
from pymatgen.core.structure import Structure
from torch.utils.data import DataLoader, Dataset
from chgnet.model import CHGNet

# %%
data_path = '/scratch/yangzd/materials/data/MPtrj_2022.9_full.json'

graph_converter = CrystalGraphConverter(atom_graph_cutoff=5, bond_graph_cutoff=3)
dataset = StructureJsonData(data_path, graph_converter, targets="ef")
train_loader, val_loader, test_loader = dataset.get_train_val_test_loader(train_ratio=0.9, val_ratio=0.05)

# %%
chgnet = CHGNet()
trainer = Trainer(
    model=chgnet,
    targets="ef",
    optimizer="Adam",
    criterion="MSE",
    learning_rate=1e-3,
    epochs=50,
    use_device="cuda",
)
trainer.train(train_loader, val_loader, test_loader)

Log output

Epoch: [0][1/44451] | Time (1.624)(0.338) | Loss 0.3169(0.3169) | MAE e 0.403(0.403)  f 0.052(0.052)
Epoch: [0][100/44451] | Time (0.623)(0.335) | Loss 0.5776(1.4586) | MAE e 0.412(0.477)  f 0.139(0.206)
Epoch: [0][200/44451] | Time (0.626)(0.339) | Loss 0.4351(1.6517) | MAE e 0.399(0.458)  f 0.116(0.208)
Epoch: [0][300/44451] | Time (0.892)(0.607) | Loss 0.9594(1.2858) | MAE e 0.511(0.443)  f 0.238(0.192)
...
Epoch: [0][26300/44451] | Time (0.996)(0.654) | Loss 1.3189(0.6118) | MAE e 0.160(0.188)  f 0.425(0.217)
Epoch: [0][26400/44451] | Time (0.995)(0.653) | Loss 0.3473(0.6110) | MAE e 0.214(0.188)  f 0.263(0.217)
Epoch: [0][26500/44451] | Time (0.998)(0.655) | Loss 124.5792(1.6960) | MAE e 0.684(0.189)  f 2.491(0.220)
Epoch: [0][26600/44451] | Time (0.996)(0.654) | Loss 0.6696(641.2061) | MAE e 0.470(0.191)  f 0.318(0.249)
Epoch: [0][26700/44451] | Time (0.995)(0.653) | Loss 3.6322(638.8499) | MAE e 0.445(0.192)  f 0.847(0.251)
Epoch: [0][26800/44451] | Time (0.998)(0.656) | Loss 6.0389(636.4801) | MAE e 0.522(0.193)  f 0.643(0.252)
....
Epoch: [0][37300/44451] | Time (1.015)(0.665) | Loss 1.2740(1311.9422) | MAE e 0.544(0.279)  f 0.345(0.567)
Epoch: [0][37400/44451] | Time (1.015)(0.664) | Loss 2.2951(1308.5920) | MAE e 0.447(0.280)  f 0.466(0.567)
Epoch: [0][37500/44451] | Time (1.017)(0.666) | Loss 5.7568(1305.1261) | MAE e 0.596(0.280)  f 0.605(0.567)
Epoch: [0][37600/44451] | Time (1.016)(0.666) | Loss 26822.4453(1302.3834) | MAE e 0.540(0.281)  f 15.234(0.567)
Epoch: [0][37700/44451] | Time (1.016)(0.665) | Loss 13.8838(1299.0148) | MAE e 0.538(0.281)  f 0.703(0.567)
Epoch: [0][37800/44451] | Time (1.015)(0.664) | Loss 2.9397(1295.8719) | MAE e 0.441(0.282)  f 0.345(0.567)

Code of Conduct

  • I agree to follow this project's Code of Conduct

`ase.filters` `ModuleNotFoundError` in example notebook

Email (Optional)

[email protected]

Version

v0.3.0

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Screen Shot 2024-02-21 at 4 12 44 PM Hi, when I tried to use the notebook example, I got this error and I don't know how to fix it, could you help me?

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Unused `get_loader()`

Can we delete get_loader()? Looks like it's an unused utility function.

def get_loader(dataset, batch_size=64, num_workers=0, pin_memory=True):
"""Get a dataloader from a dataset.
Args:
dataset (Dataset): The dataset to partition.
batch_size (int): The batch size for the data loaders
Default = 64
num_workers (int): The number of worker processes for loading the data
see torch Dataloader documentation for more info
Default = 0
pin_memory (bool): Whether to pin the memory of the data loaders
Default: True
Returns:
data_loader
"""
data_loader = DataLoader(
dataset,
batch_size=batch_size,
collate_fn=collate_graphs,
shuffle=True,
num_workers=num_workers,
pin_memory=pin_memory,
)

[Bug]: `pip install chgnet` failed

Version

v0.3.7

Which OS(es) are you using?

  • MacOS (M3 Chip, MacOS 14.5)
  • Windows
  • Linux (Ubuntu 22.04, AMD EPYC 7763 CPU)

What happened?

pip install chgnet seems to fail for the latest v0.3.7 release, which also seems to impact the pymatgen CI: https://github.com/materialsproject/pymatgen/actions/runs/9350037332/job/25732649581?pr=3822

Code snippet

pip install chgnet

Log output

Building wheels for collected packages: chgnet, nvidia-ml-py3
  Building wheel for chgnet (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for chgnet (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [60 lines of output]
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-11.1-arm64-cpython-311
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet
      copying chgnet/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      copying chgnet/graph/graph.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      copying chgnet/graph/converter.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      copying chgnet/graph/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      copying chgnet/graph/crystalgraph.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/utils
      copying chgnet/utils/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/utils
      copying chgnet/utils/vasp_utils.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/utils
      copying chgnet/utils/common_utils.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/utils
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/basis.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/functions.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/encoders.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/model.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/composition_model.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/layers.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      copying chgnet/model/dynamics.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/model
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/data
      copying chgnet/data/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/data
      copying chgnet/data/dataset.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/data
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/trainer
      copying chgnet/trainer/__init__.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/trainer
      copying chgnet/trainer/trainer.py -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/trainer
      running egg_info
      writing chgnet.egg-info/PKG-INFO
      writing dependency_links to chgnet.egg-info/dependency_links.txt
      writing requirements to chgnet.egg-info/requires.txt
      writing top-level names to chgnet.egg-info/top_level.txt
      reading manifest file 'chgnet.egg-info/SOURCES.txt'
      adding license file 'LICENSE'
      writing manifest file 'chgnet.egg-info/SOURCES.txt'
      copying chgnet/graph/cygraph.pyx -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/graph
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.2.0
      copying chgnet/pretrained/0.2.0/README.md -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.2.0
      copying chgnet/pretrained/0.2.0/chgnet_0.2.0_e30f77s348m32.pth.tar -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.2.0
      creating build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.3.0
      copying chgnet/pretrained/0.3.0/README.md -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.3.0
      copying chgnet/pretrained/0.3.0/chgnet_0.3.0_e29f68s314m37.pth.tar -> build/lib.macosx-11.1-arm64-cpython-311/chgnet/pretrained/0.3.0
      running build_ext
      Compiling chgnet/graph/cygraph.pyx because it changed.
      [1/1] Cythonizing chgnet/graph/cygraph.pyx
      building 'chgnet.graph.cygraph' extension
      creating build/temp.macosx-11.1-arm64-cpython-311
      creating build/temp.macosx-11.1-arm64-cpython-311/chgnet
      creating build/temp.macosx-11.1-arm64-cpython-311/chgnet/graph
      clang -DNDEBUG -fwrapv -O2 -Wall -fPIC -O2 -isystem /opt/anaconda3/include -arch arm64 -fPIC -O2 -isystem /opt/anaconda3/include -arch arm64 -I/opt/anaconda3/include/python3.11 -c chgnet/graph/cygraph.c -o build/temp.macosx-11.1-arm64-cpython-311/chgnet/graph/cygraph.o
      chgnet/graph/cygraph.c:1238:10: fatal error: 'fast_converter_libraries/create_graph.c' file not found
      #include "fast_converter_libraries/create_graph.c"
               ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for chgnet
  Building wheel for nvidia-ml-py3 (setup.py) ... done
  Created wheel for nvidia-ml-py3: filename=nvidia_ml_py3-7.352.0-py3-none-any.whl size=19172 sha256=390a142b23fbf3b4250902e0cd4810b5670230854a2c459a82b8ecd5c2d2a0a2
  Stored in directory: /Users/yang/Library/Caches/pip/wheels/47/50/9e/29dc79037d74c3c1bb4a8661fb608e8674b7e4260d6a3f8f51
Successfully built nvidia-ml-py3
Failed to build chgnet
ERROR: Could not build wheels for chgnet, which is required to install pyproject.toml-based projects

Code of Conduct

  • I agree to follow this project's Code of Conduct

Does `CHGNetCalculator` work with ASE

Does the CHGNetCalculator work with ASE? As I try to run the code using

chgnet = CHGNet.load()
pot = CHGNetCalculator(
        potential=chgnet, 
        properties = 'energy',
        compute_stress = True, 
        compute_hessian = False, 
        stress_weight=0.01)
        
atoms = read_vasp("POSCAR")
atoms.calc = pot
print(atoms)
qn = BFGS(atoms, trajectory='initial.traj')
qn.run(fmax=0.5)

It gives me this error:

return json.JSONEncoder.default(self, obj)
  File "/home/*****/miniconda3/lib/python3.9/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type CHGNet is not JSON serializable

Calculating the energy of element Cs

Hello.
I would like to use CHGNet to calculate the energy of the element Cs. But when I use chgnet.predict_structure , I see an error like this:
"graph_id=None has isolated atom with r_cutoff=5, should be skipped", stating that Cs is an isolated atom with atoms that are farther than 5 A from each other. I could not solve this problem with simply increasing the r_cutoff like this: CHGNet.r_cutoff = 10.0. So, I would like to ask for your assistance for solving this problem. Thank you and have a good day.

[Feature Request]: add option to disable data shuffle in `chgnet/data/dataset.py`

Email (Optional)

[email protected]

Problem

Right now, StructureData, CIFData, GraphData, and StructureJsonData shuffle the order of data in the constructor. For example, StructureData does random.shuffle(self.keys) in the constructor body. I would like to have an option to disable the shuffling.

Proposed Solution

I would like to add a keyword argument in the constructor, shuffle: bool = True to enable the user to disable shuffling. The resulting code in the constructor body can look like this, again for the example of StructureData:

if shuffle:
    random.shuffle(self.keys)

With the default value of True, it would not affect the default behavior.

Alternatives

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

[Feature Request]: interface with torch geometric

Email (Optional)

No response

Problem

Machine learning researchers often keep data in the pytorch geometric format. Applying CHGNet to this data is currently not easily supported.

Furthermore, batch evaluation of the network is extremely unwieldy as it is, this would help address that issue.

Proposed Solution

I would propose to add a method to CHGNet which would work something like CHGNet.predict_geometric(data: torch_geometric.data.Data) -> CHGNetOutput.

Alternatives

Another option would be to introduce a converter from pytorch geometric format to your format.

Code of Conduct

  • I agree to follow this project's Code of Conduct

vasp OUTCAR

Email (Optional)

[email protected]

Version

3

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

1.from chgnet.utils import parse_vasp_dir

./my_vasp_calc_dir contains vasprun.xml OSZICAR etc.

dataset_dict = parse_vasp_dir(file_root="../../../PBS_O_WORKDIR/H2")
print(dataset_dict.keys())
but:
I found that my OUTCAR does not have the member attributes required by the dataset, and I do not know what your OUTCAR looks like

Code snippet

126     dataset = {
127         "structure": [],
128         "uncorrected_total_energy": [],
129         "energy_per_atom": [],
130         "force": [],
131         "magmom": [],
132         "stress": None if "stress" not in vasprun_orig.ionic_steps[0] else [],
133     }

Log output

vergence)
    148         dataset["stress"].append(ionic_step["stress"])
    150 if dataset["uncorrected_total_energy"] == []:
--> 151     raise Exception(f"No data parsed from {file_root}!")
    153 return dataset

Exception: No data parsed from ../../../PBS_O_WORKDIR/H2!

Code of Conduct

  • I agree to follow this project's Code of Conduct

[Bug]: License issue

Email (Optional)

No response

Version

all

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Your current pyproject.toml has the lines

classifiers = [
    "Intended Audience :: Science/Research",
    "License :: OSI Approved :: MIT License",
....

causing you to show up as MIT on pypi
image
https://pypi.org/project/chgnet/

Your license looks like BSD-3 clause with an extra paragraph. I believe

License :: OSI Approved :: BSD License
or
License :: Other/Proprietary License (because of the extra paragraph)

would be a more appropriate classifier.

ref: https://pypi.org/classifiers/

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

problem with ase.filters

Email (Optional)

No response

Version

0.3.3

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Hello.
I have installed the latest version of chgnet and I am unable to initialize it.
chgnet version 0.3.3
ase version 3.22.1

Code snippet

from chgnet.model.model import CHGNet

Log output

ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 from chgnet.model.model import CHGNet

File ~/miniconda3/lib/python3.11/site-packages/chgnet/model/__init__.py:3
      1 from __future__ import annotations
----> 3 from chgnet.model.dynamics import CHGNetCalculator, MolecularDynamics, StructOptimizer
      4 from chgnet.model.model import CHGNet
      6 __all__ = ["CHGNet", "StructOptimizer", "MolecularDynamics", "CHGNetCalculator"]

File ~/miniconda3/lib/python3.11/site-packages/chgnet/model/dynamics.py:13
     11 from ase import Atoms, units
     12 from ase.calculators.calculator import Calculator, all_changes, all_properties
---> 13 from ase.filters import Filter, FrechetCellFilter
     14 from ase.md.npt import NPT
     15 from ase.md.nptberendsen import Inhomogeneous_NPTBerendsen, NPTBerendsen

ModuleNotFoundError: No module named 'ase.filters'

Code of Conduct

  • I agree to follow this project's Code of Conduct

Confusion about the version of numpy

I get the code running under the environment with numpy 1.21.6. It went wrong and said "File "pymatgen\util\coord_cython.pyx", line 1, in init pymatgen.util.coord_cython ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 96 from C header, got 88 from PyObject". So I update the numpy to higher version like 1.22.0 or 1.23.0. It went wrong as well, said"C:\Users\86469\anaconda3\envs\chgnet\lib\site-packages\ase\md\nvtberendsen.py:95: RuntimeWarning: divide by zero encountered in scalar divide(self.temperature / old_temperature - 1.0) *".

Out-of-memory when finetuning large datasets with graphs

Hi CHGNet devs, I am trying to finetune a model on the Open Catalyst Project dataset (https://github.com/Open-Catalyst-Project/ocp/blob/main/DATASET.md). I've run into memory problems when converting the dataset into graphs.

I have been following fine_tuning.ipynb and make_graphs.py in examples. I am able to convert the structures into graphs, but due to the scale of the dataset, memory runs out before I can make a labels.json file.

I can create labels for each individual graph or for smaller batches of the full dataset, but it looks like GraphData in data/dataset.py can only load a single labels.json. Is there a way to batch load labels into a single dataset, or to merge smaller datasets together? Some way to get around the memory problem and train on the full dataset?

[Bug]: issue with cuda device allocation on HPC

Email (Optional)

[email protected]

Version

v0.3.4

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I am trying to run an optimization with CHGNet on a local compute cluster, but the calculations are failing ~90% of the time. I am getting errors like the one in the log output below when CHGNet.load() tries to send the model to a cuda device.
It seems like on the local HPC cluster, I can't request a specific cuda device, but CHGNet.load() is trying to do that anyway within the load function (lines 709-718 in model/model.py, reproduced below in the code snippet). I have not had this issue with the MACE calculator, which simply uses device = "cuda".

Could the model = model.to(device) statement be wrapped in a try/except that catches the RunTimeError if this type of allocation is not permitted? Thanks so much!

Code snippet

# Determine the device to use
        if use_device == "mps" and torch.backends.mps.is_available():
            device = "mps"
        else:
            device = use_device or ("cuda" if torch.cuda.is_available() else "cpu")
            if device == "cuda":
                device = f"cuda:{cuda_devices_sorted_by_free_mem()[-1]}"
        # Move the model to the specified device
        model = model.to(device)

Log output

Traceback (most recent call last):
  File "/home/gridsan/ahoffman/htvs/djangochem/asecalcs/ase_calc_opt.py", line 87, in <module>
    opt = AseOpt.from_file(args.paramsfile)
  File "/home/gridsan/ahoffman/htvs/djangochem/asecalcs/ase_calc.py", line 78, in from_file
    return cls(jobspec)
  File "/home/gridsan/ahoffman/htvs/djangochem/asecalcs/ase_calc.py", line 70, in __init__
    self.calculator = self.get_calculator()
  File "/home/gridsan/ahoffman/htvs/djangochem/asecalcs/ase_calc.py", line 147, in get_calculator
    potential = CHGNet.load()
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/chgnet/model/model.py", line 718, in load
    model = model.to(device)
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1160, in to
    return self._apply(convert)
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/torch/nn/modules/module.py", line 810, in _apply
    module._apply(fn)
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/torch/nn/modules/module.py", line 810, in _apply
    module._apply(fn)
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/torch/nn/modules/module.py", line 833, in _apply
    param_applied = fn(param)
  File "/home/gridsan/ahoffman/.conda/envs/htvs/lib/python3.9/site-packages/torch/nn/modules/module.py", line 1158, in convert
    return t.to(device, dtype if t.is_floating_point() or t.is_complex() else None, non_blocking)
RuntimeError: CUDA error: invalid device ordinal
CUDA kernel errors might be asynchronously reported at some other API call, so the stacktrace below might be incorrect.
For debugging consider passing CUDA_LAUNCH_BLOCKING=1.
Compile with `TORCH_USE_CUDA_DSA` to enable device-side assertions.

Code of Conduct

  • I agree to follow this project's Code of Conduct

[Bug]: magmom is None

Email (Optional)

[email protected]

Version

v0.3.3

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I am attempting to assign the charge state based on the md example.

when I use struct_with_chg = solve_charge_by_mag(structure)

I get the following error

Traceback (most recent call last):
  File "/Users/Emil/MLIP-GEN-tests/chgnet/test/print_md.py", line 18, in <module>
    struct_with_chg = solve_charge_by_mag(structure)
  File "/Users/Emil/anaconda3/envs/chgnet2/lib/python3.9/site-packages/chgnet/utils/vasp_utils.py", line 196, in solve_charge_by_mag
    if mag[idx] >= min_mag and mag[idx] < max_mag:
TypeError: 'NoneType' object is not subscriptable

I believe this is because there is no initial magmom specified and so magmom is not a site property.

In vasp_utils.py, lines 187-189 in solve_charge_by_mag could be changed to

mag = structure.site_properties.get(
        "final_magmom", structure.site_properties.get("magmom")
    )

to solve this issue.

I'm curious if this introduces other issues that I'm unaware of.

Code snippet

from chgnet.model.model import CHGNet
from chgnet.model.dynamics import MolecularDynamics
from pymatgen.core import Structure
import warnings
warnings.filterwarnings("ignore", module="pymatgen")
warnings.filterwarnings("ignore", module="ase")

structure = Structure.from_file("data/mp-18767-LiMnO2.cif")
chgnet = CHGNet.load()

md = MolecularDynamics(
    atoms=structure,
    model=chgnet,
    ensemble="nvt",
    temperature=1000,  # in K
    timestep=2,  # in femto-seconds
    trajectory="md_out.traj",
    logfile="md_out.log",
    loginterval=100,
)
md.run(50) 

from ase.io.trajectory import Trajectory
from pymatgen.io.ase import AseAtomsAdaptor
from chgnet.utils import solve_charge_by_mag

traj = Trajectory("md_out.traj")
mag = traj[-1].get_magnetic_moments()
print(mag)

# get the non-charge-decorated structure
structure = AseAtomsAdaptor.get_structure(traj[-1])
print(structure)

# get the charge-decorated structure
struct_with_chg = solve_charge_by_mag(structure)
print(struct_with_chg)

Log output

Traceback (most recent call last):
  File "/Users/Emil/MLIP-GEN-tests/chgnet/test/print_md.py", line 18, in <module>
    struct_with_chg = solve_charge_by_mag(structure)
  File "/Users/Emil/anaconda3/envs/chgnet2/lib/python3.9/site-packages/chgnet/utils/vasp_utils.py", line 196, in solve_charge_by_mag
    if mag[idx] >= min_mag and mag[idx] < max_mag:
TypeError: 'NoneType' object is not subscriptable

Code of Conduct

  • I agree to follow this project's Code of Conduct

parallel relaxation

Dear CHGNet Developers,

Is there capacity for the model to relax several crystal structures at once? It seems computations of energy, forces, and stress can easily be batched, but due to the dependence on the ASECalculator I don't see a trivial way to relax in parallel. Did I just miss it?

Thank you,
Ben

Issue with ASE

Email (Optional)

No response

Version

main

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I am installing chgnet by doing pip install. I can not run any of the provided examples. I am getting an error due to ASE of which I have the latest stable version.

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Limited speed boost when increasing `batch_size` in `model.predict_structure()`

I'm using model.predict_structure() on a list of structures, but I am seeing less speed boost (2x vs linear interpolation of 1 structure) than I would expect from the evaluation of a neural network. How did you benchmark to get the default batch size? What can I do to speed up the evaluation for a large number of structures?

I am using the fast graph converter.

image

Code to reproduce:

    model = CHGNet.load()
    with MPRester() as mpr:
        one_structure = mpr.get_structure_by_material_id("mp-1341203", final=True)

    atoms_for_ref = AseAtomsAdaptor.get_atoms(one_structure)
    atoms_for_ref.rattle(0.1)
    batch_sizes_to_test = [0.05, 0.1, 0.2]
    n_individuals_to_test = [10, 20, 50, 100, 200]

    structure = AseAtomsAdaptor.get_structure(copy.deepcopy(atoms_to_test))

    all_timings = []
    for batch_size_percent in batch_sizes_to_test:
        timings_per_batch_size = []
        for population_size in n_individuals_to_test:
            batch_size = max(int(batch_size_percent * population_size), 1)
            structures = [copy.deepcopy(structure) for i in range(population_size)]
            tic = time.time()
            model.predict_structure(copy.deepcopy(structures), batch_size=batch_size)
            time_taken = time.time() - tic
            timings_per_batch_size.append(time_taken)
        all_timings.append(timings_per_batch_size)

Thank you for your help.

`IndexError` on `predict_structure`

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

The following code snippet fails:

from chgnet.model.model import CHGNet
from pymatgen.core import Structure

chgnet = CHGNet.load()
structure = Structure.from_file('example/mp-2878.cif')
prediction = chgnet.predict_structure(structure)

for key, unit in [
    ("energy", "eV/atom"),
    ("forces", "eV/A"),
    ("stress", "GPa"),
    ("magmom", "mu_B"),
]:
    print(f"CHGNet-predicted {key} ({unit}):\n{prediction[key[0]]}\n")

Error Message

CHGNet initialized with 400,438 parameters
Traceback (most recent call last):
  File "<script>", line 6, in <module>
    prediction = chgnet.predict_structure(structure)
  File "/path/to/chgnet/model/model.py", line 551, in predict_structure
    return self.predict_graph(...)
  File "/path/to/chgnet/model/model.py", line 340, in forward
    batched_graph = BatchedGraph.from_graphs(...)
  File "/path/to/chgnet/model/model.py", line 754, in from_graphs
    center=atom_cart_coords[graph.atom_graph[:, 0]],
IndexError: tensors used as indices must be long, byte or bool tensors

[Bug]: pypi release 0.2.0 doesn't match GitHub release

Version

v0.2.0

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

  1. I have previously used version 0.2.0 for my project, but when recreating an environment and installing the version CrystalGraphConverter.forward() method no longer took the "on_isolated_atoms" argument. I saw that this was an update in version 0.2.1.

I checked the pypi distribution files and the chgnet-0.2.0-cp39-cp39-macosx_10_9_x86_64.whl and
chgnet-0.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl versions contained code consistent with the 0.2.1 release.

I noticed that the pypi distribution files were updated the day before the 0.2.1 release, so I suspect the 0.2.0 release was overwritten.
image

  1. Proposed resolution: republish version 0.2.0

Code snippet

No response

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

out-of-memory issue

My experience with chgnet is great. Thanks the team for developing and sharing it!

Recently, I got an out-of-memory issue while trying to relax a structure of 12,000 atoms. The experiment was done on an A6000 GPU having 48 GB memory. Below are a few questions:

Q1: What are the memory bottlenecks of chgnet?

Q2: Do you have a benchmark for memory usage of chgnet? My tests seem to show that 4000-atom-structure uses up 30 GB and 5000-atom-structure exceeds 48 GB. Make sense?

Q3: If the GPU memory issue cannot be resolved, should I try CPU version of chgnet? How many CPU cores are equivalent to the computing power of one decent GPU (e.g. V100) for running chgnet?

Any other suggestions?

Fine tuning CHGNet with DFT energies and forces

Dear CHGNet developers,
Hello.
I would like to request an example for how CHGNet can be trained with additional DFT data (calculated by the users). Specifically the format of the data that has to be used for training.
Thank you.

[Bug]: Error when loading trainer state using trainer.load

Email (Optional)

[email protected]

Version

v0.3.8

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

  1. I was attempting to restart a training from a particular epoch but when I try to load it using trainer.load() I get the KeyError: 'decay_fraction'. The code snippet I use to load the checkpoint is
from pathlib import Path

from chgnet.trainer import Trainer
from chgnet.model import CHGNet

def load_trainer(trainer_path: Path):
    """Load the trainer from the path"""
    # load the trainer
    trainer = Trainer.load(trainer_path)
    return trainer
if __name__ == "__main__":
    file_path = '/output/epoch4_e0_f0_sNA_mNA.pth.tar'
    trainer = load_trainer(file_path)

  1. When I saved checkpoint using torch.load the scheduler_params was empty.

The dummy script representing my initial training script is given below (in case I am doing something wrong there).

On another note: not sure if i need to raise it as another issue, I also run into issues when I set save_test_result=True in the traininer. I get the error raise TypeError(f'Object of type {o.__class__.__name__} ' TypeError: Object of type int64 is not JSON serializable.

Code snippet

# The code snippet for training
#
from pathlib import Path
import numpy as np

from pymatgen.core import Structure, Lattice
from chgnet.data.dataset import StructureData, get_train_val_test_loader
from chgnet.trainer import Trainer
from chgnet.model import CHGNet




def get_structures():
    model = CHGNet.load()
    structures = []
    energies_per_atom = []
    forces = []
    a_0 = 2.85
    lattice = Lattice.cubic(a_0)
    mo_structure = Structure(lattice, ["Mo", "Mo"], [[0, 0, 0], [0.5, 0.5, 0.5]])
    mo_structure.make_supercell([3,3,3])
    for _ in range(100):
        structure = mo_structure.copy()
        # stretch the cell by a small amount
        structure.apply_strain(np.random.uniform(-0.1, 0.1, size=3))
        # perturb all atom positions by a small amount
        structure.perturb(0.1) 
        pred = model.predict_structure(structure)

        structures.append(structure)
        energies_per_atom.append(pred["e"] + np.random.uniform(-0.1, 0.1, size=1))
        forces.append(pred["f"] + np.random.uniform(-0.01, 0.01, size=pred["f"].shape))

    return structures, energies_per_atom, forces


def train_chgnet(output_dir=, epochs):


    
    structures, energies_per_atom, forces = get_structures()
    print("Len of dataset:",len(structures))
    dataset = StructureData(
        structures=structures,
        energies=energies_per_atom,
        forces = forces
    )

    # load the trainer
    train_loader, val_loader, test_loader = get_train_val_test_loader(
        dataset, batch_size=5, train_ratio=0.9, val_ratio=0.05
    )
    train_test_split = { "train_loader": train_loader,
                         "test_loader": test_loader,
                         "val_loader": val_loader
                       }

    model = CHGNet.load()

    trainer = Trainer(
                    model=model,
                    targets='ef',
                    energy_loss_ratio=1,
                    force_loss_ratio=1,
                    stress_loss_ratio=0.1,
                    mag_loss_ratio=0.1,
                    optimizer='Adam',
                    weight_decay=0,
                    scheduler='CosLR',
                    scheduler_params={'decay_fraction': 0.5e-2},
                    criterion='Huber',
                    delta=0.1,
                    epochs=5,
                    starting_epoch=0,
                    learning_rate=5e-3,
                    use_device='cpu',
                    print_freq=1
                )

    for param in model.parameters():
        param.requires_grad = True


    Path(output_dir).mkdir(parents=True, exist_ok=True)

    trainer.train(train_loader, 
                  val_loader, 
                  test_loader, 
                  train_composition_model=False,
                  save_dir=output_dir,
                  )

if __name__ == "__main__":
    train_chgnet(output_dir='output/error', epochs=2)

Log output

CHGNet initialized with 412,525 parameters
Loaded model params = 412,525
Traceback (most recent call last):
  File "{path}/trainer_reload.py", line 31, in <module>
    trainer = load_trainer(file_path)
              ^^^^^^^^^^^^^^^^^^^^^^^
  File "{path}/trainer_reload.py", line 25, in load_trainer
    trainer = Trainer.load(trainer_path)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{path}/lib/python3.11/site-packages/chgnet/trainer/trainer.py", line 545, in load
    trainer = Trainer(model=model, **state["trainer_args"])
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "{path}/lib/python3.11/site-packages/chgnet/trainer/trainer.py", line 147, in __init__
    decay_fraction = scheduler_params.pop("decay_fraction")
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: 'decay_fraction'

Code of Conduct

  • I agree to follow this project's Code of Conduct

Periodic boundary conditions?

Hello, CHGNet seems like one of the most extensive MLIP's, but from what I understand it is only applicable to isolated molecules? Is that correct, or can we also simulate bulk materials (like FCC aluminium)? If so, how would one take care of boundary conditions? Thanks in advance!

Energy jump when bond_graph_len becomes zero

Version

0.2.1

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

When I compute the energy for a series of strained structures using CHGNet, I get a jump in the energy (and stress) when no edges remain in the bond graph (i.e., every pair of atoms is 3.0 A apart). This occurs silently, and I'm expecting the energy/stress to be smooth when the edges are broken. Am I missing something, or is there something wrong here?

Code snippet

import numpy as np
from pymatgen.core import Structure
from chgnet.model import CHGNet
import matplotlib.pyplot as plt

model = CHGNet.load()

distances = []
energies = []

struct = Structure(
    lattice=[
        [3.54216907, 0, 2.04507188],
        [1.18072406, 3.33958984, 2.04507188],
        [0, 0, 4.09014583],
    ],
    species=["Ag", "Br"],
    coords=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]],
)

for strain in np.linspace(0, 0.1, 20):
    struct_copy = struct.copy()
    struct_copy.apply_strain(strain)
    distances.append(struct_copy.distance_matrix[0][1])
    energies.append(model.predict_structure(struct_copy)["e"])

plt.plot(distances, energies, "o-")
plt.gca().set(xlabel="Distance (Å)", ylabel="Energy (eV)")
plt.show()

gh-79

Log output

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

choice of pair_style in LAMMPS

Hi!

It might be too much of a basic question, but I am trying to run MDs with CHGnet in LAMMPS but I am unable to find clarificatino on what chgnet/d3 does differently than chgnet. Could you help me with that?

Many thanks

CHGNet fails for isolated atoms

If I run a calculation on an isolated atom I get the ValueError below. This issue might happen for example during molecular dynamics.

Example:

from ase import Atoms
from chgnet.model.dynamics import CHGNetCalculator

atoms = Atoms(
    symbols=["H"], 
    positions=[[0., 0., 0.]], 
    cell=[[100.0, 0, 0], [0, 100, 0], [0, 0, 100]]
)
atoms.calc = CHGNetCalculator(use_device="cpu")
print(atoms)
print(atoms.get_potential_energy())

Output:

CHGNet initialized with 400,438 parameters
CHGNet will run on cpu
Atoms(symbols='H', pbc=False, cell=[100.0, 100.0, 100.0], calculator=CHGNetCalculator(...))
Traceback (most recent call last):
  File "./single-atom.py", line 12, in <module>
    print(atoms.get_potential_energy())
  File "/home/hellstrom/ams2023.202.r112966/bin/python3.8/lib/python3.8/site-packages/ase/atoms.py", line 731, in get_potential_energy
    energy = self._calc.get_potential_energy(self)
  File "/home/hellstrom/ams2023.202.r112966/bin/python3.8/lib/python3.8/site-packages/ase/calculators/calculator.py", line 709, in get_potential_energy
    energy = self.get_property('energy', atoms)
  File "/home/hellstrom/ams2023.202.r112966/bin/python3.8/lib/python3.8/site-packages/ase/calculators/calculator.py", line 737, in get_property
    self.calculate(atoms, [name], system_changes)
  File "/home/hellstrom/Work/python/chgnet/model/dynamics.py", line 111, in calculate
    graph = self.model.graph_converter(structure)
  File "/home/hellstrom/.scm/python/AMS2023.2.venv/lib/python3.8/site-packages/torch/nn/modules/module.py", line 1130, in _call_impl
    return forward_call(*input, **kwargs)
  File "/home/hellstrom/Work/python/chgnet/graph/converter.py", line 111, in forward
    raise ValueError(msg)
ValueError: graph_id=None has isolated atom with r_cutoff=5, should be skipped

[Feature Request]: Example Notebook for MPtrj cleaning

Email (Optional)

No response

Problem

It would be great it we could have an example notebook showing the MPtrj query pattern and cleaning. It worth noting that the MP query would need to be pinned to the v2021.11.10 to arrive at the same dataset as current MPtrj but having the notebook would enable users to recreate similar datasets for newer releases like v2023.11.1 where a large number of materials have both been added and deprecated.

Proposed Solution

Notebook should by default have a smoke_test version that would only perform the cleaning on a smaller query.

Alternatives

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

[Bug]: Error for Isolated atoms

Email (Optional)

No response

Version

v0.3.5

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

Was trying to calculate the diatomic dissociation energy curves and found chgnet could not take two isolated atoms beyond cutoff

Code snippet

from chgnet.model.dynamics import CHGNetCalculator

atoms = Atoms('HH', positions=[[0, 0, 0], [7, 0, 0]], cell=[14, 14.001, 14.002], pbc=True)
calc = CHGNetCalculator()

atoms.calc = calc

print(atoms.get_potential_energy())

Log output

IndexError: too many indices for tensor of dimension 1

Code of Conduct

  • I agree to follow this project's Code of Conduct

Atomic charges questions

Hi, I read your paper "CHGNET", and I got confusions and have some questions, You use magnetic moments to represent the atomic charges, and train the model by using its, and the informations need DFT calculations, So my question is when we predict the E,F,S,M of one structure, we have to do DFT calculations before?
Or how to define the atomic charge informations in training?
Thanks !

Pretraining hyperparameters for CHGNet

Dear Authors,

Thank you for the great work and the effort in putting up the software!

Is it possible that you can share the configuration (e.g., batch size, number of epochs, etc.) for training (not fine-tuning) CHGNet from scratch?

Way to extract final total energy and final structure from the result

Recently I have been using CHGNet for structure optimization for some high throughput screening.
I wonder if there is a way to extract the final total energy, which lies at the last line of the output of FIRE optimization. And also, the structure in the form of pymatgen.Structure or Ase.atoms is needed
I have wrote some functions for parsing that energy and structure in the output log. But I think it's a low efficient way to do so.
Is there any way to get those energy and structure object by calling the attribute?

[Bug]: VASP labels Parsing issue

Email (Optional)

No response

Version

v0.3.8

Which OS(es) are you using?

  • MacOS
  • Windows
  • Linux

What happened?

I am trying to json data and get the structures, energies and forces as shows in the fine_tuning.ipynb. However, there is an error in reading the json data. The error message shows the list indices was set as a string rather than integers.

Code snippet

dataset_dict = read_json("./my_vasp_calc_dir/chgnet_dataset.json")
structures = [Structure.from_dict(struct) for struct in dataset_dict["structure"]]
energies = dataset_dict["energy_per_atom"]
forces = dataset_dict["force"]

Log output

Traceback (most recent call last):
  File "/kfs3/scratch/dwang19/storage/data/wzy/LGFCBI/chgnet/reading.py", line 33, in <module>
    structures = [Structure.from_dict(struct)]
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dwang19/miniforge/envs/lammps/lib/python3.12/site-packages/pymatgen/core/structure.py", line 2814, in from_dict
    lattice = Lattice.from_dict(dct["lattice"])
                                ~~~^^^^^^^^^^^
  File "/home/dwang19/miniforge/envs/lammps/lib/python3.12/site-packages/pymatgen/core/structure.py", line 218, in __getitem__
    return self.sites[ind]  # type: ignore[return-value]
           ~~~~~~~~~~^^^^^
TypeError: list indices must be integers or slices, not str

Code of Conduct

  • I agree to follow this project's Code of Conduct

How to run chgnet with initial charge

Email (Optional)

No response

Problem

I am trying to optimize the charged structure. Is there any place to put the total charge inside the input? For example, If I want to calculate the total energy of the [SO4]2-, how to put the total charge -2 to the input file ? I found one parameter called set_charge that is not working.

Proposed Solution

WIll be good if we could set the total charge inside the input.

Alternatives

No response

Code of Conduct

  • I agree to follow this project's Code of Conduct

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.