Skip to content
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

[WIP] Integration and test of RSS code #84

Merged
merged 40 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
0e1bdbc
Merge branch 'JaGeo:main' into main
YuanbinLiu Jun 12, 2024
8a5745a
Update common jobs and utils, and add new RSS jobs
YuanbinLiu Jun 12, 2024
12d88b5
Revert "Merge branch 'JaGeo:main' into main"
YuanbinLiu Jun 12, 2024
df14cd9
Reapply "Merge branch 'JaGeo:main' into main"
YuanbinLiu Jun 12, 2024
406cc82
Revert "add YL to contributors"
YuanbinLiu Jun 12, 2024
c4b7144
added boltzhist code. WIP docstrings still need creating
MorrowChem Jun 13, 2024
9498e76
added docstrings, updated to numpy style
MorrowChem Jun 13, 2024
4718fb7
added airss installation to README
MorrowChem Jun 13, 2024
05ae5f7
removed airss installation from README, will be managed by conda
MorrowChem Jun 13, 2024
bcdf0a4
Merging the RSS code
YuanbinLiu Jun 21, 2024
c267c94
resolve conflict
YuanbinLiu Jul 24, 2024
f5efad2
Merge remote-tracking branch 'origin/main' into rss
YuanbinLiu Jul 24, 2024
11a7305
Resolved merge conflicts
YuanbinLiu Jul 24, 2024
d4fb6df
passed unit tests
YuanbinLiu Jul 29, 2024
baae101
add testing files
YuanbinLiu Jul 29, 2024
dac446b
merging rss code
YuanbinLiu Jul 29, 2024
4a69c6a
Remove redundant test files
YuanbinLiu Jul 29, 2024
a34fd0c
fix linting errors
YuanbinLiu Jul 30, 2024
0978476
adopt logging package
YuanbinLiu Jul 30, 2024
0efee39
fix lint errors
YuanbinLiu Jul 31, 2024
1e27fe3
fix conflicts between two workflows
YuanbinLiu Jul 31, 2024
874889a
minor revisions
YuanbinLiu Aug 1, 2024
4869604
add dgl version for installation
YuanbinLiu Aug 1, 2024
1002e1f
show installed packages
YuanbinLiu Aug 1, 2024
8371824
torch==2.2.1 for pytest
YuanbinLiu Aug 1, 2024
e04a09f
torch==2.2.1 for pytest
YuanbinLiu Aug 1, 2024
8f3c3be
torch==2.2.1 for pytest
YuanbinLiu Aug 1, 2024
cacc9b2
torchdata==0.7.1
YuanbinLiu Aug 1, 2024
daff41f
delete duplicate unit tests
YuanbinLiu Aug 1, 2024
193695c
set up installation of torchdata
YuanbinLiu Aug 1, 2024
5fdb278
modify regularization test
YuanbinLiu Aug 1, 2024
7ed1787
Add buildcell to path on github
YuanbinLiu Aug 1, 2024
67e538e
species_list is needed for the analysis plots for GAP
QuantumChemist Aug 2, 2024
091af95
species_list is needed for the analysis plots for GAP
QuantumChemist Aug 2, 2024
5d3d163
added comment
QuantumChemist Aug 2, 2024
26c609e
added checks for checking if sigma regularization is active
QuantumChemist Aug 2, 2024
26ca71b
add docstrings
QuantumChemist Aug 2, 2024
094d2d7
ignore airss
QuantumChemist Aug 2, 2024
4a09114
reduce the GAP unit test run time where accuracy isn't needed
QuantumChemist Aug 2, 2024
ba5f891
update
YuanbinLiu Aug 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,14 @@ jobs:
python -m pip install .[strict]
python -m pip cache purge
python -m pip install ase==3.23.0
- name: Print installed package versions
run: |
pip show torch torchdata
- name: Install Buildcell
run: |
curl -O https://www.mtg.msm.cam.ac.uk/files/airss-0.9.3.tgz; tar -xf airss-0.9.3.tgz; rm airss-0.9.3.tgz; cd airss; make ; make install ; make neat; cd ..
- name: Add Buildcell to PATH
run: echo "$GITHUB_WORKSPACE/airss/bin" >> $GITHUB_PATH
- name: Install Julia
run: curl -fsSL https://install.julialang.org | sh -s -- -y
- name: Set up Julia environment (Needed for ACEpotentials.jl interface)
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ share/python-wheels/
.installed.cfg
*.egg
MANIFEST
airss/

# PyInstaller
# Usually these files are written by a python script from a template
Expand Down
16 changes: 5 additions & 11 deletions autoplex/auto/phonons/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,6 @@ class CompleteDFTvsMLBenchmarkWorkflow(Maker):
Default=10.
ml_models: list[str]
list of the ML models to be used. Default is GAP.
mlip_hyper: list[dict]
list with basic MLIP hyperparameters for each model.
Default are basic GAP hyperparameters {"two_body": True, "three_body": False, "soap": True}.
hyper_para_loop: bool
making it easier to loop through several hyperparameter sets.
atomwise_regularization_list: list
Expand Down Expand Up @@ -145,7 +142,6 @@ class CompleteDFTvsMLBenchmarkWorkflow(Maker):
rattle_mc_n_iter: int = 10
w_angle: list[float] | None = None
ml_models: list[str] = field(default_factory=lambda: ["GAP"])
mlip_hyper: list[dict] | None = None
QuantumChemist marked this conversation as resolved.
Show resolved Hide resolved
hyper_para_loop: bool = False
atomwise_regularization_list: list | None = None
soap_delta_list: list | None = None
Expand All @@ -160,6 +156,7 @@ def make(
f_max: float = 40.0,
pre_xyz_files: list[str] | None = None,
pre_database_dir: str | None = None,
preprocessing_data=False,
atomwise_regularization_parameter: float = 0.1,
f_min: float = 0.01, # unit: eV Å-1
atom_wise_regularization: bool = True,
Expand Down Expand Up @@ -209,8 +206,6 @@ def make(
fit_input = {}
hyper_list: list[dict[Any, Any]] = []
bm_outputs = []
if self.mlip_hyper is None:
self.mlip_hyper = [{"two_body": True, "three_body": False, "soap": True}]

for structure, mp_id in zip(structure_list, mp_ids):
if self.add_dft_random_struct:
Expand Down Expand Up @@ -258,10 +253,10 @@ def make(
{"IsolatedAtom": {"iso_atoms_dir": [isoatoms.output["dirs"]]}}
)

for ml_model, ml_hyper in zip(self.ml_models, self.mlip_hyper):
print("pre_database_dir:", pre_database_dir)
for ml_model in self.ml_models:
add_data_fit = MLIPFitMaker(
mlip_type=ml_model,
mlip_hyper=ml_hyper,
).make(
species_list=isoatoms.output["species"],
isolated_atoms_energies=isoatoms.output["energies"],
Expand All @@ -274,6 +269,7 @@ def make(
f_min=f_min,
atom_wise_regularization=atom_wise_regularization,
auto_delta=auto_delta,
preprocessing_data=preprocessing_data,
**fit_kwargs,
)
flows.append(add_data_fit)
Expand Down Expand Up @@ -341,9 +337,7 @@ def make(
"n_sparse": n_sparse,
"delta": delta,
}
loop_data_fit = MLIPFitMaker(
mlip_type=ml_model, mlip_hyper=ml_hyper
).make(
loop_data_fit = MLIPFitMaker(mlip_type=ml_model).make(
species_list=isoatoms.output["species"],
isolated_atoms_energies=isoatoms.output["energies"],
fit_input=fit_input,
Expand Down
238 changes: 236 additions & 2 deletions autoplex/data/common/flows.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,45 @@

if TYPE_CHECKING:
from emmet.core.math import Matrix3D
from pymatgen.core import Structure

import logging
import traceback

from atomate2.forcefields.jobs import (
ForceFieldRelaxMaker,
ForceFieldStaticMaker,
GAPRelaxMaker,
)
from atomate2.vasp.jobs.core import StaticMaker
from atomate2.vasp.powerups import update_user_incar_settings
from atomate2.vasp.sets.core import StaticSetGenerator
from custodian.vasp.handlers import (
FrozenJobErrorHandler,
IncorrectSmearingHandler,
LargeSigmaHandler,
MeshSymmetryErrorHandler,
NonConvergingErrorHandler,
PotimErrorHandler,
StdErrHandler,
UnconvergedErrorHandler,
VaspErrorHandler,
)
from jobflow import Flow, Maker, Response, job
from pymatgen.core import Lattice
from pymatgen.core.structure import Structure
from pymatgen.io.ase import AseAtomsAdaptor

from autoplex.data.common.jobs import (
convert_to_extxyz,
generate_randomized_structures,
get_supercell_job,
plot_force_distribution,
)
from autoplex.data.common.utils import ElementCollection

__all__ = ["GenerateTrainingDataForTesting", "DFTStaticMaker"]

__all__ = ["GenerateTrainingDataForTesting"]
logging.basicConfig(level=logging.DEBUG, format="[%(levelname)s] %(message)s")


@dataclass
Expand Down Expand Up @@ -212,3 +233,216 @@ def static_run_and_convert(
jobs.append(conv_job)

return Response(replace=Flow(jobs), output=conv_job.output)


@dataclass
class DFTStaticMaker(Maker):
"""
Maker to set up and run VASP static calculations for input structures, including bulk, isolated atoms, and dimers.

It supports custom VASP input parameters and error handlers.

Parameters
----------
name: str
Name of the flow.
isolated_atom : bool, optional
Whether to perform calculations for isolated atoms. Default is False.
isolated_species : list[str], optional
List of species for which to perform isolated atom calculations. If None,
species will be automatically derived from the 'structures' list. Default is None.
e0_spin : bool, optional
Whether to include spin polarization in isolated atom and dimer calculations.
Default is False.
dimer : bool, optional
Whether to perform calculations for dimers. Default is False.
dimer_species : list[str], optional
List of species for which to perform dimer calculations. If None, species
will be derived from the 'structures' list. Default is None.
dimer_range : list[float], optional
Range of distances for dimer calculations. Default is [0.8, 4.8].
dimer_num : int, optional
Number of different distances to consider for dimer calculations. Default is 22.
custom_set : dict, optional
Dictionary of custom VASP input parameters. If provided, will update the
default parameters. Default is None.

Returns
-------
Response
A Response object containing the VASP jobs and the directories where
the calculations were set up.

"""

name: str = "DFT single-point calculations"
isolated_atom: bool = False
isolated_species: list[str] | None = None
e0_spin: bool = False
dimer: bool = False
dimer_species: list[str] | None = None
dimer_range: list[float] | None = None
dimer_num: int = 21
custom_set: dict | None = None

@job
def make(
self,
structures: list[Structure],
config_types: list[str] | None = None,
):
"""
Maker to set up and run VASP static calculations.

Parameters
----------
structures : list[Structure], optional
List of structures for which to run the VASP static calculations. If None,
no bulk calculations will be performed. Default is None.
config_types : list[str], optional
List of configuration types corresponding to the structures. If provided,
should have the same length as the 'structures' list. If None, defaults
to 'bulk'. Default is None.
"""
job_list = []

dirs: dict[str, list[str]] = {"dirs_of_vasp": [], "config_type": []}

default_custom_set = {
"ADDGRID": "True",
"ENCUT": 520,
"EDIFF": 1e-06,
"ISMEAR": 0,
"SIGMA": 0.01,
"PREC": "Accurate",
"ISYM": None,
"KSPACING": 0.2,
"NPAR": 8,
"LWAVE": "False",
"LCHARG": "False",
"ENAUG": None,
"GGA": None,
"ISPIN": None,
"LAECHG": None,
"LELF": None,
"LORBIT": None,
"LVTOT": None,
"NSW": None,
"SYMPREC": None,
"NELM": 100,
"LMAXMIX": None,
"LASPH": None,
"AMIN": None,
}

if self.custom_set is not None:
default_custom_set.update(self.custom_set)

custom_set = default_custom_set

custom_handlers = (
VaspErrorHandler(),
MeshSymmetryErrorHandler(),
UnconvergedErrorHandler(),
NonConvergingErrorHandler(),
PotimErrorHandler(),
FrozenJobErrorHandler(),
StdErrHandler(),
LargeSigmaHandler(),
IncorrectSmearingHandler(),
)

st_m = StaticMaker(
input_set_generator=StaticSetGenerator(user_incar_settings=custom_set),
run_vasp_kwargs={"handlers": custom_handlers},
)

if structures:
for idx, struct in enumerate(structures):
static_job = st_m.make(structure=struct)
static_job.name = f"static_bulk_{idx}"
dirs["dirs_of_vasp"].append(static_job.output.dir_name)
if config_types:
dirs["config_type"].append(config_types[idx])
else:
dirs["config_type"].append("bulk")
job_list.append(static_job)

if self.isolated_atom:
try:
if self.isolated_species is not None:
syms = self.isolated_species

elif (self.isolated_species is None) and (structures is not None):
# Get the species from the database
atoms = [AseAtomsAdaptor().get_atoms(at) for at in structures]
syms = ElementCollection(atoms).get_species()

for idx, sym in enumerate(syms):
lattice = Lattice.orthorhombic(20.0, 20.5, 21.0)
isolated_atom_struct = Structure(lattice, [sym], [[0.0, 0.0, 0.0]])
static_job = st_m.make(structure=isolated_atom_struct)
static_job.name = f"static_isolated_{idx}"
static_job = update_user_incar_settings(
static_job, {"KSPACING": 2.0}
)

if self.e0_spin:
static_job = update_user_incar_settings(
static_job, {"ISPIN": 2}
)

dirs["dirs_of_vasp"].append(static_job.output.dir_name)
dirs["config_type"].append("IsolatedAtom")
job_list.append(static_job)

except ValueError as e:
logging.error(f"Unknown species of isolated atoms! Exception: {e}")
traceback.print_exc()

if self.dimer:
try:
atoms = [AseAtomsAdaptor().get_atoms(at) for at in structures]
if self.dimer_species is not None:
dimer_syms = self.dimer_species
elif (self.dimer_species is None) and (structures is not None):
# Get the species from the database
dimer_syms = ElementCollection(atoms).get_species()
pairs_list = ElementCollection(atoms).find_element_pairs(dimer_syms)
for pair in pairs_list:
for dimer_i in range(self.dimer_num):
if self.dimer_range is not None:
dimer_distance = self.dimer_range[0] + (
self.dimer_range[1] - self.dimer_range[0]
) * float(dimer_i) / float(
self.dimer_num - 1 + 0.000000000001
)

lattice = Lattice.orthorhombic(15.0, 15.5, 16.0)
dimer_struct = Structure(
lattice,
[pair[0], pair[1]],
[[0.0, 0.0, 0.0], [dimer_distance, 0.0, 0.0]],
coords_are_cartesian=True,
)

static_job = st_m.make(structure=dimer_struct)
static_job.name = f"static_dimer_{dimer_i}"
static_job = update_user_incar_settings(
static_job, {"KSPACING": 2.0}
)

if self.e0_spin:
static_job = update_user_incar_settings(
static_job, {"ISPIN": 2}
)

dirs["dirs_of_vasp"].append(static_job.output.dir_name)
dirs["config_type"].append("dimer")
job_list.append(static_job)

except ValueError:
logging.error("Unknown atom types in dimers!")
traceback.print_exc()

return Response(replace=Flow(job_list), output=dirs)
Loading