-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into cleaner_node_association
- Loading branch information
Showing
3 changed files
with
247 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import numpy as np | ||
from pybispectrum import calc_bispectrum_names | ||
from fitsnap3lib.scrapers.ase_funcs import get_apre, create_shared_arrays | ||
|
||
|
||
def ase_scraper( | ||
s, frames, energies, forces, stresses=[[0, 0, 0], [0, 0, 0], [0, 0, 0]] | ||
): | ||
""" | ||
Custom function to allocate shared arrays used in Calculator and build the internal list of | ||
dictionaries `data` of configuration info. Customized version of `fitsnap3lib.scrapers.ase_funcs`. | ||
Args: | ||
s: fitsnap instance. | ||
frames: list or array of ASE atoms objects. | ||
energies: array of energies. | ||
forces: array of forces for all configurations. | ||
stresses: array of stresses for all configurations. | ||
Creates a list of data dictionaries `s.data` suitable for fitsnap descriptor calculation. | ||
If running in parallel, this list will be distributed over procs, so that each proc will have a | ||
portion of the list. | ||
""" | ||
|
||
create_shared_arrays(s, frames) | ||
s.data = [ | ||
collate_data(a, e, f, s) | ||
for (a, e, f, s) in zip(frames, energies, forces, stresses) | ||
] | ||
|
||
|
||
def collate_data(atoms, energy, forces, stresses): | ||
""" | ||
Function to organize fitting data for FitSNAP from ASE atoms objects. | ||
Args: | ||
atoms: ASE atoms object for a single configuration of atoms. | ||
energy: energy of a configuration. | ||
forces: numpy array of forces for a configuration. | ||
stresses: numpy array of stresses for a configuration. | ||
Returns a fitsnap data dictionary for a single configuration. | ||
""" | ||
|
||
# make a data dictionary for this config | ||
|
||
apre = get_apre(cell=atoms.cell) | ||
R = np.dot(np.linalg.inv(atoms.cell), apre) | ||
|
||
positions = np.matmul(atoms.get_positions(), R) | ||
cell = apre.T | ||
|
||
data = {} | ||
data["PositionsStyle"] = "angstrom" | ||
data["AtomTypeStyle"] = "chemicalsymbol" | ||
data["StressStyle"] = "bar" | ||
data["LatticeStyle"] = "angstrom" | ||
data["EnergyStyle"] = "electronvolt" | ||
data["ForcesStyle"] = "electronvoltperangstrom" | ||
data["Group"] = "Displaced_BCC" | ||
data["File"] = None | ||
data["Stress"] = stresses | ||
data["Positions"] = positions | ||
data["Energy"] = energy | ||
data["AtomTypes"] = atoms.get_chemical_symbols() | ||
data["NumAtoms"] = len(atoms) | ||
data["Forces"] = forces | ||
data["QMLattice"] = cell | ||
data["test_bool"] = 0 | ||
data["Lattice"] = cell | ||
data["Rotation"] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) | ||
data["Translation"] = np.zeros((len(atoms), 3)) | ||
data["eweight"] = 1.0 | ||
data["fweight"] = 1.0 / 150.0 | ||
data["vweight"] = 0.0 | ||
|
||
return data | ||
|
||
|
||
def subsample_twojmax(total_bispect, twojmax_lst): | ||
bi_spect_names_str_lst = [str(lst) for lst in total_bispect] | ||
twojmax_master_str_lst = [ | ||
[str(lst) for lst in calc_bispectrum_names(twojmax=tjm)] for tjm in twojmax_lst | ||
] | ||
ind_lst = [ | ||
[desc in desc_lst for desc in bi_spect_names_str_lst] | ||
for desc_lst in twojmax_master_str_lst | ||
] | ||
return ind_lst |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
from mpi4py import MPI | ||
from fitsnap3lib.fitsnap import FitSnap | ||
from pyiron_base import PythonTemplateJob, DataContainer | ||
from pyiron_lanl.fitsnap.common import ase_scraper | ||
|
||
|
||
default_input = settings = { | ||
"BISPECTRUM": { | ||
"numTypes": 1, | ||
"twojmax": 8, | ||
"rcutfac": 4.812302818, | ||
"rfac0": 0.99363, | ||
"rmin0": 0.0, | ||
"wj": 1.0, | ||
"radelem": 0.5, | ||
"type": "Be", | ||
"wselfallflag": 0, | ||
"chemflag": 0, | ||
"bzeroflag": 0, | ||
"quadraticflag": 0, | ||
}, | ||
"CALCULATOR": { | ||
"calculator": "LAMMPSSNAP", | ||
"energy": 1, # Calculate energy descriptors | ||
"force": 1, # Calculate force descriptors | ||
"stress": 0, # Calculate virial descriptors | ||
}, | ||
"REFERENCE": { | ||
"units": "metal", | ||
"atom_style": "atomic", | ||
"pair_style": "hybrid/overlay zero 10.0 zbl 4.0 4.8", | ||
"pair_coeff1": "* * zero", | ||
"pair_coeff2": "1 1 zbl 74 74", | ||
}, | ||
"SOLVER": {"solver": "SVD", "compute_testerrs": 1, "detailed_errors": 1}, | ||
"EXTRAS": { | ||
"dump_descriptors": 0, | ||
"dump_truth": 0, | ||
"dump_weights": 0, | ||
"dump_dataframe": 0, | ||
}, | ||
"MEMORY": {"override": 0}, | ||
} | ||
|
||
|
||
class FitsnapJob(PythonTemplateJob): | ||
def __init__(self, project, job_name): | ||
super(FitsnapJob, self).__init__(project, job_name) | ||
self.__version__ = "0.1" | ||
self.__name__ = "FitsnapJob" | ||
self.input.update(default_input) | ||
self._lst_of_struct = [] | ||
self._lst_of_energies = [] | ||
self._lst_of_forces = [] | ||
self._coefficients = [] | ||
|
||
@property | ||
def list_of_structures(self): | ||
return self._lst_of_struct | ||
|
||
@list_of_structures.setter | ||
def list_of_structures(self, structure_lst): | ||
self._lst_of_struct = structure_lst | ||
|
||
@property | ||
def list_of_energies(self): | ||
return self._lst_of_energies | ||
|
||
@list_of_energies.setter | ||
def list_of_energies(self, energies): | ||
self._lst_of_energies = energies | ||
|
||
@property | ||
def coefficients(self): | ||
return self._coefficients | ||
|
||
@property | ||
def list_of_forces(self): | ||
return self._lst_of_forces | ||
|
||
@list_of_forces.setter | ||
def list_of_forces(self, forces): | ||
self._lst_of_forces = forces | ||
|
||
def run_static(self): | ||
comm = MPI.COMM_WORLD | ||
input_dict = self.input.to_builtin() | ||
snap = FitSnap(input_dict, comm=comm, arglist=["--overwrite"]) | ||
ase_scraper( | ||
snap, self._lst_of_struct, self._lst_of_energies, self._lst_of_forces | ||
) | ||
snap.process_configs() | ||
snap.solver.perform_fit() | ||
self._coefficients = snap.solver.fit | ||
self.status.finished = True | ||
|
||
def to_hdf(self, hdf=None, group_name=None): | ||
super(FitsnapJob, self).to_hdf(hdf=hdf, group_name=group_name) | ||
|
||
def from_hdf(self, hdf=None, group_name=None): | ||
super(FitsnapJob, self).from_hdf(hdf=hdf, group_name=group_name) |