Skip to content

Commit

Permalink
Merge pull request autoatml#176 from QuantumChemist/manual_supercells
Browse files Browse the repository at this point in the history
Manual supercells
  • Loading branch information
JaGeo authored Oct 25, 2024
2 parents e1dc90c + 9a0ecbb commit 25662d8
Show file tree
Hide file tree
Showing 85 changed files with 540 additions and 74 deletions.
5 changes: 5 additions & 0 deletions autoplex/auto/phonons/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ def make(
if self.add_dft_phonon_struct:
add_dft_phon = self.add_dft_phonons(
structure=structure,
mp_id=mp_id,
displacements=self.displacements,
symprec=self.symprec,
phonon_bulk_relax_maker=self.phonon_bulk_relax_maker,
Expand Down Expand Up @@ -448,6 +449,7 @@ def make(
@staticmethod
def add_dft_phonons(
structure: Structure,
mp_id: str,
displacements: list[float],
symprec: float,
phonon_bulk_relax_maker: BaseVaspMaker,
Expand All @@ -461,6 +463,8 @@ def add_dft_phonons(
----------
structure: Structure
pymatgen Structure object
mp_id: str
materials project id
displacements: list[float]
displacement distance for phonons
symprec: float
Expand All @@ -481,6 +485,7 @@ def add_dft_phonons(
"""
dft_phonons = dft_phonopy_gen_data(
structure=structure,
mp_id=mp_id,
displacements=displacements,
symprec=symprec,
phonon_bulk_relax_maker=phonon_bulk_relax_maker,
Expand Down
11 changes: 10 additions & 1 deletion autoplex/auto/phonons/jobs.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ def complete_benchmark( # this function was put here to prevent circular import
else:
dft_phonons = dft_phonopy_gen_data(
structure=benchmark_structure,
mp_id=benchmark_mp_ids[ibenchmark_structure],
displacements=[displacement],
symprec=symprec,
phonon_bulk_relax_maker=phonon_bulk_relax_maker,
Expand Down Expand Up @@ -294,6 +295,7 @@ def run_supercells(
@job(data=["phonon_data"])
def dft_phonopy_gen_data(
structure: Structure,
mp_id: str,
displacements,
symprec,
phonon_bulk_relax_maker,
Expand All @@ -308,6 +310,8 @@ def dft_phonopy_gen_data(
----------
structure: Structure
pymatgen Structure object.
mp_id: str
materials project id
phonon_displacement_maker : .BaseVaspMaker or None
Maker used to compute the forces for a supercell.
phonon_bulk_relax_maker: BaseVaspMaker
Expand All @@ -327,7 +331,9 @@ def dft_phonopy_gen_data(
jobs = []
dft_phonons_output = {}
dft_phonons_dir_output = []
supercell_matrix = reduce_supercell_size(structure, **supercell_settings)
supercell_matrix = supercell_settings.get(mp_id, {}).get("supercell_matrix")
if not supercell_matrix:
supercell_matrix = reduce_supercell_size(structure, **supercell_settings)

if phonon_displacement_maker is None:
phonon_displacement_maker = TightDFTStaticMaker(name="dft phonon static")
Expand All @@ -337,6 +343,7 @@ def dft_phonopy_gen_data(
run_vasp_kwargs={"handlers": {}},
input_set_generator=TightRelaxSetGenerator(
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand All @@ -360,6 +367,7 @@ def dft_phonopy_gen_data(
input_set_generator=StaticSetGenerator(
auto_ispin=False,
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand Down Expand Up @@ -488,6 +496,7 @@ def dft_random_gen_data(
run_vasp_kwargs={"handlers": {}},
input_set_generator=TightRelaxSetGenerator(
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISYM": 0, # to be changed
Expand Down
100 changes: 62 additions & 38 deletions autoplex/data/phonons/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@
from atomate2.forcefields.jobs import (
ForceFieldRelaxMaker,
ForceFieldStaticMaker,
GAPRelaxMaker,
GAPStaticMaker,
M3GNetRelaxMaker,
M3GNetStaticMaker,
MACERelaxMaker,
MACEStaticMaker,
NequipRelaxMaker,
NequipStaticMaker,
)
from atomate2.vasp.flows.core import DoubleRelaxMaker
from atomate2.vasp.flows.phonons import PhononMaker
Expand Down Expand Up @@ -85,6 +77,7 @@ class TightDFTStaticMaker(PhononDisplacementMaker):
input_set_generator: VaspInputGenerator = field(
default_factory=lambda: StaticSetGenerator(
user_incar_settings={
"ALGO": "Normal", # not switching to Fast because it's not precise enough for the fit
"IBRION": -1,
"ISPIN": 1,
"ISMEAR": 0,
Expand All @@ -93,7 +86,6 @@ class TightDFTStaticMaker(PhononDisplacementMaker):
"EDIFF": 1e-7,
"LAECHG": False,
"LREAL": False,
"ALGO": "Normal", # not switching to Fast because it's not precise enough for the fit
"NSW": 0,
"LCHARG": False, # Do not write the CHGCAR file
"LWAVE": False, # Do not write the WAVECAR file
Expand Down Expand Up @@ -216,6 +208,7 @@ class DFTPhononMaker(PhononMaker):
run_vasp_kwargs={"handlers": {}},
input_set_generator=TightRelaxSetGenerator(
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand All @@ -239,6 +232,7 @@ class DFTPhononMaker(PhononMaker):
input_set_generator=StaticSetGenerator(
auto_ispin=False,
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand Down Expand Up @@ -329,6 +323,7 @@ class RandomStructuresDataGenerator(Maker):
run_vasp_kwargs={"handlers": {}},
input_set_generator=TightRelaxSetGenerator(
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISYM": 0, # to be changed
Expand Down Expand Up @@ -391,18 +386,23 @@ def make(
jobs.append(relaxed)
structure = relaxed.output.structure

supercell_matrix_job = reduce_supercell_size_job(
structure=structure,
min_length=self.supercell_settings.get("min_length", 12),
max_length=self.supercell_settings.get("max_length", 25),
fallback_min_length=self.supercell_settings.get("fallback_min_length", 10),
max_atoms=self.supercell_settings.get("max_atoms", 500),
min_atoms=self.supercell_settings.get("min_atoms", 50),
step_size=self.supercell_settings.get("step_size", 1.0),
supercell_matrix = self.supercell_settings.get(mp_id, {}).get(
"supercell_matrix"
)
jobs.append(supercell_matrix_job)

supercell_matrix = supercell_matrix_job.output
if not supercell_matrix:
supercell_matrix_job = reduce_supercell_size_job(
structure=structure,
min_length=self.supercell_settings.get("min_length", 12),
max_length=self.supercell_settings.get("max_length", 25),
fallback_min_length=self.supercell_settings.get(
"fallback_min_length", 10
),
max_atoms=self.supercell_settings.get("max_atoms", 500),
min_atoms=self.supercell_settings.get("min_atoms", 50),
step_size=self.supercell_settings.get("step_size", 1.0),
)
jobs.append(supercell_matrix_job)
supercell_matrix = supercell_matrix_job.output

random_rattle_sc = generate_randomized_structures(
structure=structure,
Expand Down Expand Up @@ -567,15 +567,20 @@ class MLPhononMaker(FFPhononMaker):
min_length: float | None = 20.0
displacement: float = 0.01
bulk_relax_maker: ForceFieldRelaxMaker | None = field(
default_factory=lambda: GAPRelaxMaker(
relax_cell=True, relax_kwargs={"interval": 500}
default_factory=lambda: ForceFieldRelaxMaker(
relax_cell=True,
relax_kwargs={"interval": 500},
force_field_name="GAP",
)
)
phonon_displacement_maker: ForceFieldStaticMaker | None = field(
default_factory=lambda: GAPStaticMaker(name="gap phonon static")
default_factory=lambda: ForceFieldStaticMaker(
name="gap phonon static",
force_field_name="GAP",
)
)
static_energy_maker: ForceFieldStaticMaker | None = field(
default_factory=lambda: GAPStaticMaker()
default_factory=lambda: ForceFieldStaticMaker(force_field_name="GAP")
)
store_force_constants: bool = False
get_supercell_size_kwargs: dict = field(
Expand Down Expand Up @@ -654,13 +659,18 @@ def make_from_ml_model(
calculator_kwargs.update({"model_path": str(potential_file)})

ml_prep = ml_phonon_maker_preparation(
bulk_relax_maker=NequipRelaxMaker(
relax_cell=True, relax_kwargs={"interval": 500}
bulk_relax_maker=ForceFieldRelaxMaker(
relax_cell=True,
relax_kwargs={"interval": 500},
force_field_name="Nequip",
),
phonon_displacement_maker=ForceFieldStaticMaker(
name="nequip phonon static",
force_field_name="Nequip",
),
phonon_displacement_maker=NequipStaticMaker(
name="nequip phonon static"
static_energy_maker=ForceFieldStaticMaker(
force_field_name="Nequip",
),
static_energy_maker=NequipStaticMaker(),
calculator_kwargs=calculator_kwargs,
relax_maker_kwargs=self.relax_maker_kwargs,
static_maker_kwargs=self.static_maker_kwargs,
Expand All @@ -671,13 +681,18 @@ def make_from_ml_model(
calculator_kwargs = {"path": str(potential_file)}

ml_prep = ml_phonon_maker_preparation(
bulk_relax_maker=M3GNetRelaxMaker(
relax_cell=True, relax_kwargs={"interval": 500}
bulk_relax_maker=ForceFieldRelaxMaker(
relax_cell=True,
relax_kwargs={"interval": 500},
force_field_name="M3GNet",
),
phonon_displacement_maker=M3GNetStaticMaker(
name="m3gnet phonon static"
phonon_displacement_maker=ForceFieldStaticMaker(
name="m3gnet phonon static",
force_field_name="M3GNet",
),
static_energy_maker=ForceFieldStaticMaker(
force_field_name="M3GNet",
),
static_energy_maker=M3GNetStaticMaker(),
calculator_kwargs=calculator_kwargs,
relax_maker_kwargs=self.relax_maker_kwargs,
static_maker_kwargs=self.static_maker_kwargs,
Expand All @@ -696,11 +711,18 @@ def make_from_ml_model(
)

ml_prep = ml_phonon_maker_preparation(
bulk_relax_maker=MACERelaxMaker(
relax_cell=True, relax_kwargs={"interval": 500}
bulk_relax_maker=ForceFieldRelaxMaker(
relax_cell=True,
relax_kwargs={"interval": 500},
force_field_name="MACE",
),
phonon_displacement_maker=ForceFieldStaticMaker(
name="mace phonon static",
force_field_name="MACE",
),
static_energy_maker=ForceFieldStaticMaker(
force_field_name="MACE",
),
phonon_displacement_maker=MACEStaticMaker(name="mace phonon static"),
static_energy_maker=MACEStaticMaker(),
calculator_kwargs=calculator_kwargs,
relax_maker_kwargs=self.relax_maker_kwargs,
static_maker_kwargs=self.static_maker_kwargs,
Expand Down Expand Up @@ -754,6 +776,7 @@ class IsoAtomStaticMaker(StaticMaker):
default_factory=lambda: StaticSetGenerator(
user_kpoints_settings={"reciprocal_density": 1},
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand Down Expand Up @@ -804,6 +827,7 @@ def make(
isolated_atom_static_input_set = StaticSetGenerator(
user_kpoints_settings={"grid_density": 1},
user_incar_settings={
"ALGO": "Normal",
"ISPIN": 1,
"LAECHG": False,
"ISMEAR": 0,
Expand Down
25 changes: 23 additions & 2 deletions docs/user/generation/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ and demonstrates that a robust database of **crystalline structures** for MLIP r
be build by generating the single-atom displaced supercells using `phonopy` and combining them with a set of rattled supercell
structures, generated from the same unit cell models.

## `phonopy` generated structures
## Single-atom displaced supercell structures

The single-atom displaced supercell structures used in `autoplex` are generated by [phonopy](https://phonopy.github.io/phonopy/vasp.html) VASP-related routines,
that are collected in the `dft_phonopy_gen_data` flow
Expand Down Expand Up @@ -45,7 +45,7 @@ Where `pre_xyz_files` can also take a train and test database as argument, e.g.
`autoplex` is equipped with a [DFTPhononMaker](#autoplex.data.phonons.flows.DFTPhononMaker) class that inherits from the `atomate2` [PhononMaker](https://materialsproject.github.io/atomate2/reference/atomate2.vasp.flows.phonons.PhononMaker.html#atomate2.vasp.flows.phonons.PhononMaker) with
specific VASP input adjustments to guarantee high quality fit data. It can be used to run individual and customized `phonopy` workflows to generate MLIP fit data.

## Rattled structures
## Rattled supercell structures

There are several ways available in `autoplex` to rattle supercell structures,
that are collected in the `dft_random_gen_data` flow
Expand Down Expand Up @@ -96,7 +96,28 @@ As a counterpart to the `DFTPhononMaker` for generating data, `autoplex` include
that can be used to construct customized randomized structures workflows.
`autoplex` provides a variety of [utility](#autoplex.data.common.utils) subroutines to further customize a workflow.
## Adjust supercell settings
You can adjust the supercell settings by passing a dictionary containing your specific supercell settings for each
MP-ID to `CompleteDFTvsMLBenchmarkWorkflow`, e.g. like:
```python
mp_id = "mp-22905"
supercell_settings = {
mp_id: {
"supercell_matrix": [[0, 2, 0], [0, 0, 2], [2, 0, 0]]
},
"min_length": 11,
"max_length": 25,
"max_atoms": 200,
}
complete_flow = CompleteDFTvsMLBenchmarkWorkflow(
...,
supercell_settings=supercell_settings,
...).make(...)
```
To keep the calculations consistent, this will adjust the settings of single-atom displaced and rattled supercells.
## VASP settings
Expand Down
Loading

0 comments on commit 25662d8

Please sign in to comment.