Using FAIR chemistry models and workflow tools like quacc for inorganic materials science#

We’re going to use quacc along with FAIR chem calculators for some simple recipes to calculate elastic and phonon properties. quacc has the nice property that you can also use many different workflow managers like jobflow, dask, or prefect to scale and parallelize many calculations, including both ML and DFT calculations.

Quick setup (without a workflow backend)#

  1. First, make sure you installed fairchem[quacc] to pick up an appropriate version of quacc and the phonon dependencies.

  2. We’re going to use OMat24 machine learning interatomic potentials (MLIPs), which require approval and a license agreement.

    1. Navigate to the OMat24 model repo, login with your HuggingFace account, and request access to the gated models if you haven’t already

    2. Make sure huggingface_hub has access to the repo by running huggingface-cli login and following the instructions: a. Navigate to HuggingFace tokens b. Click “+Create new token” c. type OMat24 in the Repositories permissions field d. Click create token e. Type the token into the CLI, or alternatively you can run huggingface-cli login --token YOUR_TOKEN_HERE. You can also set the environment variable HF_TOKEN=YOUR_TOKEN_HERE if that’s more convenient.

  3. Set up quacc to use your favorite workflow tool (dask, prefect, etc) by setting your quacc configuration. a. Tip: If you just want to run like this tutorial is, write a simple file with WORKFLOW_ENGINE: null in ~/.quacc.yaml. This is by far the easiest way to get started if you don’t want to worry about parallelization/etc

Example of a simple relaxation#

In quacc, a job is a fundamental block of work that can be run in parallel with other jobs. A flow is a sequence of jobs that need to be run to accomplish a goal. See the quacc docs for more information about how this works!

We’re going to start simple here - let’s run a local relaxation (optimize the unit cell and positions) using a pre-trained EquiformerV2-31M-OMAT24-MP-sAlex checkpoint. This checkpoint has a few fun properties

  1. It’s a relatively small (31M) parameter model

  2. It was pre-trained on the OMat24 dataset, and then fine-tuned on the MPtrj and Alexandria datasets, so it should emit energies and forces that are consistent with the MP GGA (PBE/PBE+U) level of theory

This code will download the appropriate checkpoint from huggingface_hub automatically; if you don’t have the right access token specified, you’ll hit an permission or 401 error.

import pprint

from ase.build import bulk
from ase.optimize import LBFGS
from quacc.recipes.mlp.core import relax_job

# Make an Atoms object of a bulk Cu structure
atoms = bulk("Cu")

# Run a structure relaxation
result = relax_job(
    atoms,
    method="fairchem",
    model_name="EquiformerV2-31M-OMAT24-MP-sAlex",
    local_cache="./fairchem_checkpoint_cache/",
    opt_params={"fmax": 1e-3, "optimizer": LBFGS},
)
WARNING:quacc.recipes.mlp._base:CUDA is not available to PyTorch. Calculations will be slow.
INFO:root:Project root: /home/runner/work/fairchem/fairchem/src/fairchem
/home/runner/work/fairchem/fairchem/src/fairchem/core/models/scn/spherical_harmonics.py:23: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  _Jd = torch.load(os.path.join(os.path.dirname(__file__), "Jd.pt"))
/home/runner/work/fairchem/fairchem/src/fairchem/core/models/equiformer_v2/wigner.py:10: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  _Jd = torch.load(os.path.join(os.path.dirname(__file__), "Jd.pt"))
/home/runner/work/fairchem/fairchem/src/fairchem/core/models/escn/so3.py:23: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  _Jd = torch.load(os.path.join(os.path.dirname(__file__), "Jd.pt"))
INFO:root:Checking local cache: ./fairchem_checkpoint_cache/ for model EquiformerV2-31M-OMAT24-MP-sAlex
/home/runner/work/fairchem/fairchem/src/fairchem/core/common/relaxation/ase_utils.py:200: FutureWarning: You are using `torch.load` with `weights_only=False` (the current default value), which uses the default pickle module implicitly. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling (See https://github.com/pytorch/pytorch/blob/main/SECURITY.md#untrusted-models for more details). In a future release, the default value for `weights_only` will be flipped to `True`. This limits the functions that could be executed during unpickling. Arbitrary objects will no longer be allowed to be loaded via this mode unless they are explicitly allowlisted by the user via `torch.serialization.add_safe_globals`. We recommend you start setting `weights_only=True` for any use case where you don't have full control of the loaded file. Please open an issue on GitHub for any issues related to this experimental feature.
  checkpoint = torch.load(checkpoint_path, map_location=torch.device("cpu"))
INFO:root:amp: true
cmd:
  checkpoint_dir: /home/runner/work/fairchem/fairchem/docs/core/checkpoints/2025-03-29-04-41-36
  commit: core:b88b66e,experimental:NA
  identifier: ''
  logs_dir: /home/runner/work/fairchem/fairchem/docs/core/logs/wandb/2025-03-29-04-41-36
  print_every: 100
  results_dir: /home/runner/work/fairchem/fairchem/docs/core/results/2025-03-29-04-41-36
  seed: null
  timestamp_id: 2025-03-29-04-41-36
  version: 0.1.dev1+gb88b66e
dataset:
  a2g_args:
    r_energy: true
    r_forces: true
    r_stress: true
  format: ase_db
  transforms:
    decompose_tensor:
      decomposition:
        stress_anisotropic:
          irrep_dim: 2
        stress_isotropic:
          irrep_dim: 0
      rank: 2
      tensor: stress
    element_references:
      file: /fsx-ocp-med/shared/alex-10M/alex-mp-norms-refs/element_references.pt
    normalizer:
      file: /fsx-ocp-med/shared/alex-10M/alex-mp-norms-refs/normalizers.pt
evaluation_metrics:
  metrics:
    energy:
    - mae
    - mae_density
    forces:
    - mae
    - forcesx_mae
    - forcesy_mae
    - forcesz_mae
    - cosine_similarity
    stress:
    - mae
    - mae_density
    stress_anisotropic:
    - mae
    stress_isotropic:
    - mae
  primary_metric: energy_mae
gp_gpus: null
gpus: 0
logger: wandb
loss_functions:
- energy:
    coefficient: 20
    fn: mae_density
- forces:
    coefficient: 10
    fn: l2mae
- stress_isotropic:
    coefficient: 1
    fn: mae
- stress_anisotropic:
    coefficient: 1
    fn: mae
    reduction: mean_all
model:
  backbone:
    alpha_drop: 0.1
    attn_activation: silu
    attn_alpha_channels: 64
    attn_hidden_channels: 64
    attn_value_channels: 16
    avg_degree: 61.94676351484548
    avg_num_nodes: 31.16592360068011
    distance_function: gaussian
    drop_path_rate: 0.1
    edge_channels: 128
    enforce_max_neighbors_strictly: false
    ffn_activation: silu
    ffn_hidden_channels: 128
    grid_resolution: 18
    lmax_list:
    - 4
    max_neighbors: 20
    max_num_elements: 96
    max_radius: 12.0
    mmax_list:
    - 2
    model: equiformer_v2_backbone
    norm_type: layer_norm_sh
    num_distance_basis: 512
    num_heads: 8
    num_layers: 8
    num_sphere_samples: 128
    otf_graph: true
    proj_drop: 0.0
    share_atom_edge_embedding: false
    sphere_channels: 128
    use_atom_edge_embedding: true
    use_attn_renorm: true
    use_gate_act: false
    use_grid_mlp: true
    use_m_share_rad: false
    use_pbc: true
    use_pbc_single: true
    use_s2_act_attn: false
    use_sep_s2_act: true
    weight_init: uniform
  heads:
    energy:
      module: fairchem.core.models.equiformer_v2.heads.EqV2ScalarHead
    forces:
      module: fairchem.core.models.equiformer_v2.heads.EqV2VectorHead
    stress:
      decompose: true
      module: fairchem.core.models.equiformer_v2.heads.Rank2SymmetricTensorHead
      output_name: stress
      use_source_target_embedding: true
  name: hydra
  otf_graph: true
  pass_through_head_outputs: true
optim:
  batch_size: 8
  clip_grad_norm: 100
  ema_decay: 0.999
  eval_batch_size: 12
  eval_every: 3000
  load_balancing: atoms
  lr_initial: 0.0002
  max_epochs: 16
  num_workers: 8
  optimizer: AdamW
  optimizer_params:
    weight_decay: 0.001
  scheduler: LambdaLR
  scheduler_params:
    epochs: 741904
    lambda_type: cosine
    lr: 0.0002
    lr_min_factor: 0.01
    warmup_epochs: 463
    warmup_factor: 0.2
outputs:
  energy:
    level: system
    property: energy
  forces:
    eval_on_free_atoms: true
    level: atom
    property: forces
    train_on_free_atoms: true
  stress:
    decomposition:
      stress_anisotropic:
        eval_on_free_atoms: true
        irrep_dim: 2
        level: system
        parent: stress
        train_on_free_atoms: true
      stress_isotropic:
        eval_on_free_atoms: true
        irrep_dim: 0
        level: system
        parent: stress
        train_on_free_atoms: true
    level: system
    property: stress
relax_dataset: {}
slurm:
  account: ocp
  cpus_per_task: 9
  folder: /fsx-ocp-med/lbluque/logs/omat-alex-mp/S2EFS/train/4478177
  gpus_per_node: 8
  job_id: '4478177'
  job_name: eqV2_31M_ft_alexmptraj_e20_f10_s1_cos16
  mem: 480GB
  nodes: 4
  ntasks_per_node: 8
  partition: learn
  qos: ocp_high
  time: 4320
task: {}
test_dataset: {}
trainer: ocp
val_dataset: {}
INFO:root:Loading model: hydra
INFO:root:Loaded HydraModel with 31207434 parameters.
INFO:root:Loading checkpoint in inference-only mode, not loading keys associated with trainer state!
WARNING:root:No seed has been set in modelcheckpoint or OCPCalculator! Results may not be reproducible on re-run
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-28-280071-91021
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-28-280071-91021
pprint.pprint(result)
{'atoms': Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]]),
 'converged': True,
 'dir_name': '/home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-28-280071-91021',
 'input_atoms': {'atoms': Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]]),
                 'structure_metadata': {'builder_meta': {'build_date': datetime.datetime(2025, 3, 29, 4, 42, 28, 773179, tzinfo=datetime.timezone.utc),
                                                         'emmet_version': '0.84.6rc6',
                                                         'pymatgen_version': '2025.1.9'},
                                        'chemsys': 'Cu',
                                        'composition': Composition('Cu1'),
                                        'composition_reduced': Composition('Cu1'),
                                        'density': 8.971719813140734,
                                        'density_atomic': 11.761470249999999,
                                        'elements': [Element Cu],
                                        'formula_anonymous': 'A',
                                        'formula_pretty': 'Cu',
                                        'nelements': 1,
                                        'nsites': 1,
                                        'symmetry': {'angle_tolerance': 5.0,
                                                     'crystal_system': <CrystalSystem.cubic: 'Cubic'>,
                                                     'number': 225,
                                                     'point_group': 'm-3m',
                                                     'symbol': 'Fm-3m',
                                                     'symprec': 0.1,
                                                     'version': '2.6.0'},
                                        'volume': 11.761470249999999}},
 'name': 'fairchem Relax',
 'nid': 'fv-az1377-956.04mcjwnfvh2ullqrygi5qw4vjc.dx.internal.cloudapp.net',
 'parameters': {'version': '0.1.dev1+gb88b66e'},
 'parameters_opt': {'fmax': 0.001,
                    'max_steps': 1000,
                    'maxstep': 0.2,
                    'optimizer': 'LBFGS',
                    'type': 'optimization'},
 'quacc_version': '0.13.0',
 'results': {'energy': -4.098316669464111,
             'forces': array([[1.0281279e-08, 5.0602549e-09, 7.6041227e-09]], dtype=float32),
             'stress': array([[-1.1523021e-02, -1.5406982e-08, -1.5228842e-08],
       [-1.5406982e-08, -1.1515909e-02, -1.8953735e-08],
       [-1.5228842e-08, -1.8953735e-08, -1.1517838e-02]], dtype=float32)},
 'structure_metadata': {'builder_meta': {'build_date': datetime.datetime(2025, 3, 29, 4, 42, 28, 881344, tzinfo=datetime.timezone.utc),
                                         'emmet_version': '0.84.6rc6',
                                         'pymatgen_version': '2025.1.9'},
                        'chemsys': 'Cu',
                        'composition': Composition('Cu1'),
                        'composition_reduced': Composition('Cu1'),
                        'density': 8.971719813140734,
                        'density_atomic': 11.761470249999999,
                        'elements': [Element Cu],
                        'formula_anonymous': 'A',
                        'formula_pretty': 'Cu',
                        'nelements': 1,
                        'nsites': 1,
                        'symmetry': {'angle_tolerance': 5.0,
                                     'crystal_system': <CrystalSystem.cubic: 'Cubic'>,
                                     'number': 225,
                                     'point_group': 'm-3m',
                                     'symbol': 'Fm-3m',
                                     'symprec': 0.1,
                                     'version': '2.6.0'},
                        'volume': 11.761470249999999},
 'trajectory': [Atoms(symbols='Cu', pbc=True, cell=[[0.0, 1.805, 1.805], [1.805, 0.0, 1.805], [1.805, 1.805, 0.0]], calculator=SinglePointCalculator(...))],
 'trajectory_results': [{'energy': -4.098316669464111,
                         'forces': array([[1.02812789e-08, 5.06025488e-09, 7.60412266e-09]]),
                         'stress': array([[-1.15230214e-02, -1.54069824e-08, -1.52288422e-08],
       [-1.54069824e-08, -1.15159089e-02, -1.89537346e-08],
       [-1.52288422e-08, -1.89537346e-08, -1.15178376e-02]])}]}

Congratulations; you ran your first relaxation using an OMat24-trained checkpoint and quacc!

Example of an elastic property calculation#

Let’s do something more interesting that normally takes quite a bit of work in DFT: calculating an elastic constant! Elastic properties are important to understand how strong or easy to deform a material is, or how a material might change if compressed or expanded in specific directions (i.e. the Poisson ratio!).

We don’t have to change much code from above, we just use a built-in recipe to calculate the elastic tensor from quacc. This recipe

  1. (optionally) Relaxes the unit cell using the MLIP

  2. Generates a number of deformed unit cells by applying strains

  3. For each deformation, a relaxation using the MLIP and (optionally) a single point calculation is run

  4. Finally, all of the above calculations are used to calculate the elastic properties of the material

For more documentation, see the quacc docs for quacc.recipes.mlp.elastic_tensor_flow

from ase.build import bulk
from quacc.recipes.mlp.elastic import elastic_tensor_flow

# Make an Atoms object of a bulk Cu structure
atoms = bulk("Cu")

# Run an elastic property calculation with our favorite MLP potential
result = elastic_tensor_flow(
    atoms,
    job_params={
        "all": dict(
            method="fairchem",
            model_name="EquiformerV2-31M-OMAT24-MP-sAlex",
            local_cache="./fairchem_checkpoint_cache/",
        ),
    },
)
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-29-014193-94025
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-29-014193-94025
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-29-521066-65281
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-29-521066-65281
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-29-799669-49733
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-29-799669-49733
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-30-071104-86097
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-30-071104-86097
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-30-370065-42816
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-30-370065-42816
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-30-646127-59375
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-30-646127-59375
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-30-926814-95039
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-30-926814-95039
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-31-419424-65094
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-31-419424-65094
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-31-676970-28365
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-31-676970-28365
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-31-931512-55684
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-31-931512-55684
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-32-180600-13874
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-32-180600-13874
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-32-453423-49334
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-32-453423-49334
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-32-708258-88252
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-32-708258-88252
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-32-963290-47596
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-32-963290-47596
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-33-210710-93637
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-33-210710-93637
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-33-507579-23270
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-33-507579-23270
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-33-775016-20225
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-33-775016-20225
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-34-036125-29167
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-34-036125-29167
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-34-299148-24414
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-34-299148-24414
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-34-587581-60725
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-34-587581-60725
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-35-082854-23214
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-35-082854-23214
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-35-321556-28839
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-35-321556-28839
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-35-559138-33225
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-35-559138-33225
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-35-834939-95612
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-35-834939-95612
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-36-069635-76583
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-36-069635-76583
result["elasticity_doc"].bulk_modulus
BulkModulus(voigt=188.065, reuss=188.065, vrh=188.065)

Congratulations, you ran your first elastic tensor calculation!

Example of a phonon calculation#

Phonon calculations are very important for inorganic materials science to

  • Calculate thermal conductivity

  • Understand the vibrational modes, and thus entropy and free energy, of a material

  • Predict the stability of a material at finite temperature (e.g. 300 K) among many others! We can run a similarly straightforward calculation that

  1. Runs a relaxation on the unit cell and atoms

  2. Repeats the unit cell a number of times to make it sufficiently large to capture many interesting vibrational models

  3. Generatives a number of finite displacement structures by moving each atom of the unit cell a little bit in each direction

  4. Running single point calculations on each of (3)

  5. Gathering all of the calculations and calculating second derivatives (the hessian matrix!)

  6. Calculating the eigenvalues/eigenvectors of the hessian matrix to find the vibrational modes of the material

  7. Analyzing the thermodynamic properties of the vibrational modes.

Note that this analysis assumes that all vibrational modes are harmonic, which is a pretty reasonable approximately for low/moderate temperature materials, but becomes less realistic at high temperatures.

from ase.build import bulk
from quacc.recipes.mlp.phonons import phonon_flow

# Make an Atoms object of a bulk Cu structure
atoms = bulk("Cu")

# Run a phonon (hessian) calculation with our favorite MLP potential
result = phonon_flow(
    atoms,
    method="fairchem",
    job_params={
        "all": dict(
            model_name="EquiformerV2-31M-OMAT24-MP-sAlex",
            local_cache="./fairchem_checkpoint_cache/",
        ),
    },
    min_lengths=10.0, # set the minimum unit cell size smaller to be compatible with limited github runner ram
)
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-41-742472-18819
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-41-742472-18819
INFO:quacc.runners.prep:Calculation will run at /home/runner/work/fairchem/fairchem/docs/core/tmp-quacc-2025-03-29-04-42-46-233908-65385
/opt/hostedtoolcache/Python/3.12.9/x64/lib/python3.12/site-packages/seekpath/hpkot/__init__.py:172: DeprecationWarning: dict interface is deprecated. Use attribute interface instead
  conv_lattice = dataset["std_lattice"]
INFO:quacc.runners.prep:Calculation results stored at /home/runner/work/fairchem/fairchem/docs/core/quacc-2025-03-29-04-42-46-233908-65385
print(
    f'The entropy at { result["results"]["thermal_properties"]["temperatures"][-1]:.0f} K is { result["results"]["thermal_properties"]["entropy"][-1]:.2f} kJ/mol'
)
The entropy at 1000 K is 64.56 kJ/mol

Congratulations, you ran your first phonon calculation!

Parallelizing these calculations#

These calculations are super straightforward to parallelize because of how quacc is written. Simply choose a workflow manager like parssl or prefect in quacc, and run the same code! There are many ways to run these calculations in parallel. The FAIR chemistry team regularly runs hundreds of thousands of calculations in some of these packages at scale.