Benchmark of ML-based phonon structure#

This tutorial will help you understand all the autoplex benchmark specifications.

General settings#

For the benchmark, you do not have to worry about a lot of settings. The crucial part here is the number of benchmark structures you are interested in.

from mp_api.client import MPRester
from autoplex.auto.phonons.flows import CompleteDFTvsMLBenchmarkWorkflow
from atomate2.common.schemas.phonons import PhononBSDOSDoc
from monty.serialization import loadfn

mpr = MPRester(api_key='YOUR_MP_API_KEY')
structure_list = []
benchmark_structure_list = []
mpids = ["mp-22905"]
mpbenchmark = ["mp-22905"]
dft_data = loadfn("/path/to/DFT/ref/data/PhononBSDOSDoc_mp_22905.json")
dft_reference: PhononBSDOSDoc = dft_data["output"]
for mpid in mpids:
    structure = mpr.get_structure_by_material_id(mpid)
    structure_list.append(structure)
for mpbm in mpbenchmark:
    bm_structure = mpr.get_structure_by_material_id(mpbm)
    benchmark_structure_list.append(bm_structure)

complete_flow = CompleteDFTvsMLBenchmarkWorkflow().make(
    structure_list=structure_list, mp_ids=mpids, preprocessing_data=True,
    benchmark_structures=benchmark_structure_list, benchmark_mp_ids=mpbenchmark, 
    dft_references=[dft_reference])

In case you have pre-existing DFT calculations, you can pass them as a list via the dft_references parameters. Make sure, it is the same order as in the benchmark MP-IDs and structures. It is important to provide the pre-existing DFT data in form of a PhononBSDOSDoc task document object (from atomate2). Without any DFT reference calculations given, autoplex will automatically execute the VASP calculations. A mix of pre-existing and missing DFT references is not supported.

Error metrics#

autoplex automatically provides you with a phonon bandstructure comparison plot, a q-point wise RMSE plot and an overall RMSE value (results_XY.txt file). For examples see here.

Run a benchmark with a pre-existing DFT calculation and GAP potential#

If you want to run or repeat the benchmark with your pre-existing DFT calculation and your pre-existing GAP potential, you can use the following Python script as a template. It is important to provide the pre-existing DFT data in form of a PhononBSDOSDoc task document object (from atomate2).

#!/usr/bin/env python

import os
from atomate2.common.schemas.phonons import PhononBSDOSDoc
from atomate2.forcefields.jobs import ForceFieldRelaxMaker, ForceFieldStaticMaker
from mp_api.client import MPRester
from autoplex.benchmark.phonons.flows import PhononBenchmarkMaker
from atomate2.forcefields.flows.phonons import PhononMaker
from autoplex.benchmark.phonons.jobs import write_benchmark_metrics
from monty.serialization import loadfn
from jobflow import SETTINGS
from jobflow import run_locally

os.environ["OMP_NUM_THREADS"] = "48"
os.environ["OPENBLAS_NUM_THREADS"] = "1"

store = SETTINGS.JOB_STORE
# connect to the job store
store.connect()

mpr = MPRester(api_key = 'YOUR_API_KEY')
mpid = "mp-22905"
structure =  mpr.get_structure_by_material_id(mpid)
dft_data = loadfn("/path/to/DFT/ref/data/PhononBSDOSDoc_mp_22905.json")
dft_reference: PhononBSDOSDoc = dft_data["output"]
potential_filename = "/path/to/GAP/file/gap_file.xml"

phojob = PhononMaker(
        bulk_relax_maker=ForceFieldRelaxMaker(calculator_kwargs={"args_str": "IP GAP", "param_filename": potential_filename}, 
        relax_cell=True, relax_kwargs={"interval": 500, "fmax": 0.00001}, steps=10000,
        force_field_name="GAP",
),
        phonon_displacement_maker=ForceFieldStaticMaker(calculator_kwargs={"args_str": "IP GAP", "param_filename": potential_filename},
        force_field_name="GAP",
),
        static_energy_maker=ForceFieldStaticMaker(calculator_kwargs={"args_str": "IP GAP", "param_filename": potential_filename}),
        store_force_constants=False, min_length=18,
        generate_frequencies_eigenvectors_kwargs={"units": "THz"}, force_field_name="GAP",
).make(structure=structure)
        
bm = PhononBenchmarkMaker(name="Benchmark").make(
    structure=structure, benchmark_mp_id = "mp-22905",
    displacement=0.01, atomwise_regularization_parameter=0.1,
    soap_dict={'n_sparse': 6000, 'delta': 0.5}, suffix="",  # exemplary values
    ml_phonon_task_doc = phojob.output, dft_phonon_task_doc = dft_reference)

comp_bm = write_benchmark_metrics(
            benchmark_structures=[structure],
            metrics=[[bm.output]],
        )

run_locally([phojob, bm, comp_bm], create_folders=True, store=store)

If you use another ForceFieldRelaxMaker and ForceFieldStaticMaker, you can switch from GAP to one of the other MLIP potentials.

You can extract a JSON file containing your pre-existing VASP DFT run from your MongoDB with the following script:

from jobflow import SETTINGS
from monty.json import jsanitize
from monty.serialization import dumpfn

store = SETTINGS.JOB_STORE
store.connect()

result = store.query( {'name': 'generate_frequencies_eigenvectors'}, load=True)
phononbsdosdoc = store.query({'uuid': 'put the MongoDB UUID here'}, load=True)
for i in phononbsdosdoc:
    del i["_id"]
    monty_encoded_json_doc = jsanitize(i, allow_bson=True, strict=True, enum_values=True)
    
    dumpfn(monty_encoded_json_doc, 'PhononBSDOSDoc_mp_22905.json')

And check if it contains the correct output with:

from monty.serialization import loadfn

data = loadfn('PhononBSDOSDoc_mp_22905.json')
data['output'].structure  

Your output for structure should look like:

Structure Summary
Lattice
    abc : 5.061019144638489 5.061019144638489 5.061019144638489
 angles : 90.0 90.0 90.0
 volume : 129.63251308285152
      A : 5.061019144638489 -0.0 3e-16
      B : 8e-16 5.061019144638489 3e-16
      C : 0.0 -0.0 5.061019144638489
    pbc : True True True
PeriodicSite: Li (0.0, 0.0, 0.0) [0.0, 0.0, 0.0]
PeriodicSite: Li (4e-16, 2.531, 2.531) [0.0, 0.5, 0.5]
PeriodicSite: Li (2.531, 0.0, 2.531) [0.5, 0.0, 0.5]
PeriodicSite: Li (2.531, 2.531, 3e-16) [0.5, 0.5, 0.0]
PeriodicSite: Cl (2.531, 0.0, 1.5e-16) [0.5, 0.0, 0.0]
PeriodicSite: Cl (2.531, 2.531, 2.531) [0.5, 0.5, 0.5]
PeriodicSite: Cl (0.0, 0.0, 2.531) [0.0, 0.0, 0.5]
PeriodicSite: Cl (4e-16, 2.531, 1.5e-16) [0.0, 0.5, 0.0]