Introduction to atomman: DFT reference crystal loading

Lucas M. Hale, lucas.hale@nist.gov, Materials Science and Engineering Division, NIST.

Disclaimers

1. Introduction

In addition to the crystal structures in the NIST Repository, crystal structures can also be obtained directly from the Materials Project and OQMD DFT databases. This provides a means of performing direct comparisons of crystal structure predictions between DFT and classical potentials and offers the opportunity to explore more proposed crystal structures.

Added version 1.4.0

NOTE: Fetching records from Materials Project requires that pymatgen be installed.

Library Imports

[1]:
# Standard Python libraries
import datetime

# http://www.numpy.org/
import numpy as np

import atomman as am
import atomman.unitconvert as uc

# Show atomman version
print('atomman version =', am.__version__)

# Show date of Notebook execution
print('Notebook executed on', datetime.date.today())
atomman version = 1.4.11
Notebook executed on 2024-04-29

2. atomman.load(‘prototype’)

Accesses the potentials database to retrieve a crystal_prototype record and generate a unit cell System based on it.

Query parameters

  • id (str) The reference crystal’s unique id. Combines a database tag “mp-” or “oqmd-” and the DFT database’s entry id.

  • api_key (str, optional) The user’s Materials Project API key or path to a file containing the key. Only needed for fetching structures from Materials Project and if the key is not set to the “MAPI_KEY” environment variable.

Database option parameters

  • database (atomman.library.Database, optional) A pre-defined Database object to use. If not given, will initialize a new Database object. Passing in a database can save time if multiple calls are made for the same record type.

  • local (bool, optional) Indicates if the Database object is to look for local records. Default is True. Ignored if database is given.

  • remote (bool, optional) Indicates if the Database object is to look for remote records. Default is True. Ignored if database is given.

  • refresh_cache (bool, optional) If the local database is of style “local”, indicates if the metadata cache file is to be refreshed. If False, metadata for new records will be added but the old record metadata fields will not be updated. If True, then the metadata for all records will be regenerated, which is needed to update the metadata for modified records.

  • verbose (bool, optional) If True, info messages will be printed during operations. Default value is False.

Returns

  • system (atomman.System) The system object generated from the crystal prototype.

Fetch the relaxed fcc Au structure from both databases

[3]:
mp_api_key = 'C:/Users/lmh1/Documents/Materials Project/API key.txt'

ucell = am.load('dft_reference', 'mp-81', api_key=mp_api_key, verbose=True)
print(ucell)
/home/lmh1/anaconda3/envs/py11/lib/python3.11/site-packages/pymatgen/ext/matproj.py:186: UserWarning: You are using the legacy MPRester. This version of the MPRester will no longer be updated. To access the latest data with the new MPRester, obtain a new API key from https://materialsproject.org/api and consult the docs at https://docs.materialsproject.org/ for more information.
  warnings.warn(
---------------------------------------------------------------------------
MPRestError                               Traceback (most recent call last)
File ~/anaconda3/envs/py11/lib/python3.11/site-packages/pymatgen/ext/matproj.py:288, in _MPResterLegacy._make_request(self, sub_url, payload, method, mp_decode)
    286         raise MPRestError(data["error"])
--> 288     raise MPRestError(f"REST query returned with error status code {response.status_code}")
    290 except Exception as exc:

MPRestError: REST query returned with error status code 403

During handling of the above exception, another exception occurred:

MPRestError                               Traceback (most recent call last)
File ~/Python-packages/atomman/atomman/library/Database/_reference_crystal.py:481, in fetch_mp_crystals(self, id, api_key)
    480 try:
--> 481     entries = m.query({"material_id": {"$in": aslist(id)}}, ['material_id', 'cif'])
    482 except:

File ~/anaconda3/envs/py11/lib/python3.11/site-packages/pymatgen/ext/matproj.py:1035, in _MPResterLegacy.query(self, criteria, properties, chunk_size, max_tries_per_chunk, mp_decode, show_progress_bar)
   1034 count_payload["options"] = json.dumps({"count_only": True})
-> 1035 num_results = self._make_request("/query", payload=count_payload, method="POST")
   1036 if num_results <= chunk_size:

File ~/anaconda3/envs/py11/lib/python3.11/site-packages/pymatgen/ext/matproj.py:292, in _MPResterLegacy._make_request(self, sub_url, payload, method, mp_decode)
    291 msg = f"{exc}. Content: {getattr(response, 'content', str(exc))}"
--> 292 raise MPRestError(msg)

MPRestError: REST query returned with error status code 403. Content: b'{"valid_response": false, "error": "API_KEY is not a valid key.", "version": {"db": "2020_09_08", "pymatgen": "2022.0.8", "rest": "2.0"}, "created_at": "2024-04-29T13:01:15.685814"}'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
Cell In[3], line 3
      1 mp_api_key = 'C:/Users/lmh1/Documents/Materials Project/API key.txt'
----> 3 ucell = am.load('dft_reference', 'mp-81', api_key=mp_api_key, verbose=True)
      4 print(ucell)

File ~/Python-packages/atomman/atomman/load/__init__.py:32, in load(style, *args, **kwargs)
     13 """
     14 Load a System from another format.
     15
   (...)
     28     The system object associated with the data model.
     29 """
     31 if style in load_styles:
---> 32     return load_styles[style](*args, **kwargs)
     33 elif style in failed_load_styles:
     34     raise failed_load_styles[style]

File ~/Python-packages/atomman/atomman/load/dft_reference/load.py:64, in load(id, api_key, database, local, remote, refresh_cache, verbose)
     61     database = Database.Database()
     63 # Fetch crystal from NIST or DFT database
---> 64 crystal = database.fetch_reference_crystal(id, api_key=api_key,
     65                                            local=local,
     66                                            remote=remote, 
     67                                            refresh_cache=refresh_cache,
     68                                            verbose=verbose)
     70 return crystal.ucell

File ~/Python-packages/atomman/atomman/library/Database/_reference_crystal.py:437, in fetch_reference_crystal(self, id, api_key, local, remote, refresh_cache, verbose)
    435         print('Crystal retrieved from OQMD')
    436 else:
--> 437     record = self.fetch_mp_crystal(id, api_key=api_key)
    438     if verbose:
    439         print('Crystal retrieved from Materials Project')

File ~/Python-packages/atomman/atomman/library/Database/_reference_crystal.py:525, in fetch_mp_crystal(self, id, api_key)
    522     with open(api_key) as f:
    523         api_key = f.read().strip()
--> 525 records = self.fetch_mp_crystals(id, api_key=api_key)
    526 if len(records) == 1:
    527     return records[0]

File ~/Python-packages/atomman/atomman/library/Database/_reference_crystal.py:483, in fetch_mp_crystals(self, id, api_key)
    481     entries = m.query({"material_id": {"$in": aslist(id)}}, ['material_id', 'cif'])
    482 except:
--> 483     raise ValueError('Failed to find Materials Project information')
    484 else:
    485     # Convert cif to model and save
    486     for entry in entries:

ValueError: Failed to find Materials Project information
[4]:
ucell = am.load('dft_reference', 'oqmd-592562', verbose=True)
print(ucell)
Crystal retrieved from OQMD
avect =  [ 4.125,  0.000,  0.000]
bvect =  [ 0.000,  4.125,  0.000]
cvect =  [ 0.000,  0.000,  4.125]
origin = [ 0.000,  0.000,  0.000]
natoms = 4
natypes = 1
symbols = ('Au',)
pbc = [ True  True  True]
per-atom properties = ['atype', 'pos']
     id   atype  pos[0]  pos[1]  pos[2]
      0       1   0.000   0.000   0.000
      1       1   2.063   2.063   0.000
      2       1   2.063   0.000   2.063
      3       1   0.000   2.063   2.063