-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can HTESP reproduce the Elastic Constants reported on https://next-gen.materialsproject.org? #1
Comments
Hi Zhao, Thank you for the questions. I’ve reproduced results for SrAl₄ (mp-2775) and BaAl₄ (mp-1903) using the older Materials Project database (https://legacy.materialsproject.org/), where calculations were reported for the PBE functional. In the newer database versions, I occasionally observed discrepancies, likely due to the use of different exchange-correlation functionals, such as r2SCAN. I recommend reproducing the results with PBE first, as the reported values in the current Materials Project database might not consistently reflect PBE. Additionally, for elastic calculations, a much denser k-mesh or a higher energy cutoff is necessary compared to simple ground-state calculations. Best, |
Recently, I tried using atomate2 with the following script to reproduce the Elastic Constants of mp-126 in the newer database: $ cat mp-elastic.py
# The final result is very different from: https://next-gen.materialsproject.org/materials/mp-126
#$ pyenv shell datasci
#$ module load vasp
#$ python $0
import numpy as np
from jobflow import run_locally
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from atomate2.common.schemas.elastic import ElasticDocument
from atomate2.vasp.flows.elastic import ElasticMaker
from atomate2.vasp.powerups import (
update_user_incar_settings,
update_user_potcar_functional,
update_user_kpoints_settings,
)
from pymatgen.core import Structure
from mp_api.client import MPRester
from atomate2.vasp.powerups import add_metadata_to_flow
user_potcar_functional = "PBE_64"
with MPRester() as mpr:
elasticity_docs = mpr.materials.elasticity.search(material_ids=["mp-126"])
structure = elasticity_docs[0].structure
structure = SpacegroupAnalyzer(structure).get_conventional_standard_structure()
flow = ElasticMaker().make(structure, conventional=True)
flow = update_user_incar_settings(flow, {
"GGA": "PE",
"ISMEAR": 2,
"SIGMA": 0.05
})
flow = update_user_potcar_functional(flow, user_potcar_functional)
# (Optional) add metadata to the flow task document.
# Could be useful to filter specific results from the database.
# For e.g., adding material project ID for the compound, use following lines
flow = add_metadata_to_flow(
flow=flow,
additional_fields={"mp_id": "mp-126", "submission_label": "mp-126_elastic_tensor-GGA-PE"},
)
responses = run_locally(flow, create_folders=True, ensure_success=True)
elastic_output = responses[flow.jobs[-1].uuid][1].output
matrix = np.array(elastic_output.elastic_tensor.ieee_format)
np.set_printoptions(precision=4, suppress=True)
print(matrix) The result is as follows:
Could you please give me some hints on how to adjust the above script?
Do you have checked the detailed tasks list corresponding to a specific material, say this one in the case: The GGA Deformation should correspond to the elastic computations. Regards, |
HTESP utilizes the Pymatgen package to calculate elastic constants. You can find more details on Pymatgen’s elasticity module (https://pymatgen.org/pymatgen.analysis.elasticity.html#module-pymatgen.analysis.elasticity). I haven't worked with the Atomate2 package yet, so I can't provide a specific answer regarding its integration or use. I recommend reaching out directly to the Atomate2 development team, as they may be able to offer more targeted guidance for your questions. Best, |
We can use the following method to identify the logical relationships of the actual input files used by a specific computational task. Say, for this one: https://next-gen.materialsproject.org/materials/mp-126/tasks, take one of the GGA Deformation tasks, then the previous structure optimization task for this can be identified as follows: In [29]: from mp_api.client import MPRester
...: from pymatgen.core.structure import Structure
...: from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
...:
...: with MPRester() as mpr:
...: # 获取形变计算的input_structure信息
...: deform_task = mpr.materials.tasks.search(task_ids=["mp-2383896"])[0]
...: input_dict = deform_task.transformations['history'][0]['input_structure']
...: input_structure = Structure.from_dict(input_dict)
...:
...: # 标准化input结构
...: sga_input = SpacegroupAnalyzer(input_structure)
...: std_input = sga_input.get_conventional_standard_structure()
...:
...: print("=== Deformation Task Input Structure (Standardized) ===")
...: print(std_input)
...:
...: # 搜索匹配的结构优化计算
...: material_doc = mpr.materials.search(material_ids=["mp-126"])[0]
...: calc_types = material_doc.calc_types
...:
...: for mpid, calc_type in calc_types.items():
...: task_doc = mpr.materials.tasks.search(task_ids=[mpid])[0]
...:
...: if hasattr(task_doc, 'output') and hasattr(task_doc.output, 'structure'):
...: opt_structure = task_doc.output.structure
...: # 标准化优化结构
...: sga_opt = SpacegroupAnalyzer(opt_structure)
...: std_opt = sga_opt.get_conventional_standard_structure()
...:
...: # 直接比较标准化后的结构
...: if std_input == std_opt:
...: print("\n=== Matching Structure Optimization ===")
...: print(f"Task ID: {mpid}")
...: print(f"Calc Type: {calc_type}")
...: print("Standardized Structure:")
...: print(std_opt)
...:
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 14463.12it/s]
=== Deformation Task Input Structure (Standardized) ===
Full Formula (Pt4)
Reduced Formula: Pt
abc : 3.976419 3.976419 3.976419
angles: 90.000000 90.000000 90.000000
pbc : True True True
Sites (4)
# SP a b c
--- ---- --- --- ---
0 Pt 0 0 0
1 Pt 0 0.5 0.5
2 Pt 0.5 0 0.5
3 Pt 0.5 0.5 0
Retrieving MaterialsDoc documents: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12052.60it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12264.05it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12052.60it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11214.72it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11848.32it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12264.05it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11915.64it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11305.40it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11881.88it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12264.05it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11748.75it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11683.30it/s]
Retrieving TaskDoc documents: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 8422.30it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12372.58it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12018.06it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12228.29it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12595.51it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12520.31it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12228.29it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12052.60it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12336.19it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12087.33it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11554.56it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12052.60it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11983.73it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12710.01it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12157.40it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12052.60it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11983.73it/s]
=== Matching Structure Optimization ===
Task ID: mp-2383760
Calc Type: GGA Structure Optimization
Standardized Structure:
Full Formula (Pt4)
Reduced Formula: Pt
abc : 3.976419 3.976419 3.976419
angles: 90.000000 90.000000 90.000000
pbc : True True True
Sites (4)
# SP a b c
--- ---- --- --- ---
0 Pt 0 0 0
1 Pt 0 0.5 0.5
2 Pt 0.5 0 0.5
3 Pt 0.5 0.5 0
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12409.18it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12192.74it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11683.30it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11915.64it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 11554.56it/s]
Retrieving TaskDoc documents: 100%|██████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 12446.01it/s] Furthermore, we can reproduce the corresponding calculation results using the same original input files from each sub-task of the corresponding workflow. See materialsproject/pymatgen#3884 (reply in thread) for the related discussion. Regards, |
Hi Zhao, Currently, HTESP extracts data only using the materials ID. It would be beneficial to add the capability to extract data based on the task as well, which could be implemented in the near future. Thanks ! Best, |
So far, I have successfully replicated the results reported by the Materials Project, relying entirely on its original data, as demonstrated below. #https://github.com/JaGeo/TutorialAtomate2Forcefields/issues/4
#$ pyenv shell datasci
#$ module load vasp
#$ python $0
#https://materialsproject.github.io/atomate2/user/docs_schemas_emmet.html
# I have successfully replicated the results reported by [the Materials Project](https://next-gen.materialsproject.org/materials/mp-126), relying entirely on its original data, as demonstrated below.
#https://github.com/Neraaz/HTESP/issues/1#issuecomment-2451363600
import numpy as np
from jobflow import run_locally
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from atomate2.vasp.flows.elastic import ElasticMaker
from atomate2.vasp.powerups import (
update_user_incar_settings,
update_user_potcar_functional,
update_user_kpoints_settings,
)
from pymatgen.io.vasp.inputs import Kpoints
from pymatgen.core import Structure
from mp_api.client import MPRester
from atomate2.vasp.powerups import add_metadata_to_flow
#https://github.com/materialsproject/atomate2/issues/1014#issuecomment-2454955891
from atomate2.vasp.flows.mp import MPGGADoubleRelaxMaker, MPGGAStaticMaker
# All the following versions are the same one in this case:
#werner@x13dai-t:~/Public/hpc/vasp/pot$ ug 'PAW_PBE Pt '
#potcar/POTPAW_PBE_52/Pt/PSCTR: TITEL = PAW_PBE Pt 04Feb2005
#potcar/POTPAW_PBE_52/Pt/POTCAR: PAW_PBE Pt 04Feb2005
#potcar/POTPAW_PBE_52/Pt/POTCAR: TITEL = PAW_PBE Pt 04Feb2005
#potcar/POT_PAW_PBE_64/Pt/PSCTR: TITEL = PAW_PBE Pt 04Feb2005
#potcar/POT_PAW_PBE_64/Pt/POTCAR: PAW_PBE Pt 04Feb2005
#potcar/POT_PAW_PBE_64/Pt/POTCAR: TITEL = PAW_PBE Pt 04Feb2005
#potcar/POTPAW_PBE_54/Pt/PSCTR: TITEL = PAW_PBE Pt 04Feb2005
#potcar/POTPAW_PBE_54/Pt/POTCAR: PAW_PBE Pt 04Feb2005
#potcar/POTPAW_PBE_54/Pt/POTCAR: TITEL = PAW_PBE Pt 04Feb2005
#user_potcar_functional = "PBE_64"
#user_potcar_functional = "PBE_52_W_HASH"
#user_potcar_functional = "PBE_54_W_HASH"
#要复现MP,根据下面的检查,应该设置potcar版本与MP官方使用的一致。
#In [4]: from mp_api.client import MPRester
# ...:
# ...: material_id = "mp-126"
# ...: with MPRester() as mpr:
# ...: # 获取elastic数据来获取task id
# ...: elasticity_doc = mpr.materials.elasticity.search(material_ids=[material_id])
# ...: opt_id = elasticity_doc[0].fitting_data.optimization_task.string
# ...:
# ...: # 使用task id获取详细信息
# ...: opt_doc = mpr.materials.tasks.search([opt_id],
# ...: fields=["input", "calcs_reversed"])
# ...:
# ...: # 提取 potcar_spec
# ...: potcar_spec = opt_doc[0].calcs_reversed[0].input.potcar_spec
# ...: print(f"POTCAR specifications: {potcar_spec}")
# ...:
#Retrieving ElasticityDoc documents: 100%|█████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 7543.71it/s]
#Retrieving TaskDoc documents: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 9892.23it/s]
#POTCAR specifications: [PotcarSpec(titel='PAW_PBE Pt 05Jan2001', hash='a604ea3c6a9cc23c739b762f625cf449', summary_stats=None)]
#In [4]: opt_doc[0].calcs_reversed[0].input.potcar_spec
#Out[4]: [PotcarSpec(titel='PAW_PBE Pt 05Jan2001', hash='a604ea3c6a9cc23c739b762f625cf449', summary_stats=None)]
#https://github.com/materialsproject/api/issues/944#issuecomment-2503063154
user_potcar_functional = "PBE"
# 实际测试表明,不同的vasp版本的计算结果是一致的(差别很小,可以忽略):
#In [5]: # MP所使用的vasp版本:
# ...: for calc in opt_doc[0].calcs_reversed:
# ...: print(calc.vasp_version)
# ...:
#5.4.4
#5.4.4
material_id = "mp-126"
with MPRester() as mpr:
# Obtain elastic data and the related task IDs.
elasticity_doc = mpr.materials.elasticity.search(material_ids=[material_id])
opt_id = elasticity_doc[0].fitting_data.optimization_task.string
first_deform_id = str(elasticity_doc[0].fitting_data.deformation_tasks[0])
opt_doc = mpr.materials.tasks.search([opt_id],
fields=["input", "orig_inputs", "calcs_reversed"])
deform_dep_doc = mpr.materials.tasks.search([first_deform_id],
fields=["input", "orig_inputs", "calcs_reversed"])
structure = mpr.materials.get_structure_by_material_id(material_id)
structure = SpacegroupAnalyzer(structure).get_conventional_standard_structure()
# Process kpoints settings
#opt_kpoints_settings = opt_doc[0].orig_inputs.kpoints
#deform_kpoints_settings = deform_dep_doc[0].orig_inputs.kpoints
# Use calcs-reversed to do the trick:
#https://materialsproject.github.io/atomate2/user/docs_schemas_emmet.html#calcs-reversed
opt_kpoints_settings = opt_doc[0].calcs_reversed[0].input.kpoints
deform_kpoints_settings = deform_dep_doc[0].calcs_reversed[0].input.kpoints
# Process INCAR settings
# Adopt the following strategy: based on the keys in `orig_inputs.incar`, use the corresponding values from `input.parameters`.
# This can be simplified into a one-liner dictionary comprehension:
#opt_incar_settings = {key: opt_doc[0].input.parameters[key] for key in opt_doc[0].orig_inputs.incar.keys() if key in opt_doc[0].input.parameters}
#deform_incar_settings = {key: deform_dep_doc[0].input.parameters[key] for key in deform_dep_doc[0].orig_inputs.incar.keys() if key in deform_dep_doc[0].input.parameters}
# Or, for better readability, you can first define variables and then achieve it as following:
#orig_incar = opt_doc[0].orig_inputs.incar
#input_params = opt_doc[0].input.parameters
#opt_incar_settings = {key: input_params[key] for key in orig_incar.keys() if key in input_params}
#orig_incar = deform_dep_doc[0].orig_inputs.incar
#input_params = deform_dep_doc[0].input.parameters
#deform_incar_settings = {key: input_params[key] for key in orig_incar.keys() if key in input_params}
# Use calcs-reversed to do the trick:
#https://materialsproject.github.io/atomate2/user/docs_schemas_emmet.html#calcs-reversed
opt_incar_settings = opt_doc[0].calcs_reversed[0].input.incar
deform_incar_settings = deform_dep_doc[0].calcs_reversed[0].input.incar
# Handle MAGMOM settings correctly.
if isinstance(opt_incar_settings.get("MAGMOM", []), list):
magmoms = {}
for idx, site in enumerate(structure):
if idx < len(opt_incar_settings.get("MAGMOM", [])):
magmoms[site.species_string] = opt_incar_settings["MAGMOM"][idx]
opt_incar_settings["MAGMOM"] = magmoms
if isinstance(deform_incar_settings.get("MAGMOM", []), list):
magmoms = {}
for idx, site in enumerate(structure):
if idx < len(deform_incar_settings.get("MAGMOM", [])):
magmoms[site.species_string] = deform_incar_settings["MAGMOM"][idx]
deform_incar_settings["MAGMOM"] = magmoms
#Re: The meaning of "GGA = --".
#https://www.vasp.at/forum/viewtopic.php?p=29678#p29678
#If the GGA tag is not explicitly specified in INCAR, then the functional from the POTCAR (usually PBE) is used. With older VASP versions, this was indicated with "GGA = --" in OUTCAR. Since VASP.6.4.3 this is properly indicated with "GGA = PE".
#In [3]: opt_doc[0].input.parameters['GGA']
#Out[3]: '--'
#In [34]: opt_doc[0].calcs_reversed[0].input.potcar
#Out[34]: ['Pt']
#In [35]: opt_doc[0].calcs_reversed[0].input.potcar_spec
#Out[35]: [PotcarSpec(titel='PAW_PBE Pt 05Jan2001', hash='a604ea3c6a9cc23c739b762f625cf449', summary_stats=None)]
#In [36]: opt_doc[0].calcs_reversed[0].input.potcar_type
#Out[36]: ['PAW_PBE']
flow = ElasticMaker(
bulk_relax_maker=MPGGADoubleRelaxMaker(), # 使用MP的双重优化设置
elastic_relax_maker=MPGGAStaticMaker(), # 使用MP的静态计算设置
).make(structure, conventional=True)
flow = update_user_potcar_functional(flow, user_potcar_functional)
flow = update_user_kpoints_settings(flow, opt_kpoints_settings, name_filter="MP GGA relax")
flow = update_user_kpoints_settings(flow, deform_kpoints_settings, name_filter="MP GGA static")
flow = update_user_incar_settings(flow, opt_incar_settings, name_filter="MP GGA relax" )
flow = update_user_incar_settings(flow, deform_incar_settings, name_filter="MP GGA static")
# Add metadata.
#flow = add_metadata_to_flow(
# flow=flow,
# additional_fields={
# "mp_id": "mp-126",
# "submission_label": "mp-126_elastic_tensor-GGA-PE"
# },
#)
# Run the flow
responses = run_locally(flow, create_folders=True, ensure_success=True)
elastic_output = responses[flow.jobs[-1].uuid][1].output
matrix = np.array(elastic_output.elastic_tensor.ieee_format)
np.set_printoptions(precision=4, suppress=True)
print(matrix) The result is as follows: $ module load vasp/5.4.4.pl2-oneapi.2022.3.0
$ pyenv shell datasci
$ python reproduce-mp-elastic.py
[[299.9534 221.5266 221.5266 0. 0. -0. ]
[221.5266 299.9534 221.5266 0. 0. -0. ]
[221.5266 221.5266 299.9534 0. 0. -0. ]
[ 0. 0. 0. 58.8789 -0. 0. ]
[ 0. 0. 0. -0. 58.8789 0. ]
[ -0. -0. -0. 0. 0. 58.8789]] As you can see, the result is the same as the one reported by the Materials Project: In [8]: from mp_api.client import MPRester
...:
...: with MPRester() as mpr:
...: elasticity_doc = mpr.materials.elasticity.search(material_ids=["mp-126"])
...: print(elasticity_doc[0].elastic_tensor.raw)
...:
Retrieving ElasticityDoc documents: 100%|████████████████████████████████████████████████████████████████████████████████████████████| 1/1 [00:00<00:00, 17924.38it/s]
((300.4965181204997, 221.77204403016452, 221.77204403016452, 1.5543122344752188e-15, 1.3322676295501875e-15, 5.551115123125781e-15), (221.77204403016452, 300.4965181204997, 221.77204403016458, 1.3322676295501875e-15, 1.5543122344752188e-15, 2.791547977519229e-14), (221.77204403016452, 221.77204403016458, 300.49651812049973, 6.661338147750939e-16, 5.551115123125784e-15, 1.5543122344752182e-15), (1.5543122344752188e-15, 1.3322676295501875e-15, 6.661338147750939e-16, 57.738028947926864, 0.0, -2.440413917789469e-31), (1.3322676295501875e-15, 1.5543122344752188e-15, 5.551115123125784e-15, 0.0, 57.73802894792688, -1.602552228361556e-15), (5.551115123125781e-15, 2.791547977519229e-14, 1.5543122344752182e-15, -2.440413917789469e-31, -1.602552228361556e-15, 57.73802894792694)) Next, I will use the above method to reproduce the elastic constants of https://next-gen.materialsproject.org/materials/mp-126 with HTESP. See below for the related discussions: Regards, |
I wonder whether HTESP can reproduce the Elastic Constants reported on https://next-gen.materialsproject.org, e.g., this one: https://next-gen.materialsproject.org/materials/mp-126?
Regards,
Zhao
The text was updated successfully, but these errors were encountered: