As library
2024 May 31
Requirements:
- CrySPY 1.3.0 or later
Cryspy can be used as a library to generate random structures or structures by evolutionary algoritym. The jupyter notebook is available in CrySPY utility > notebook > as_library.
Random structure generation
####
#### when you change set_logger(), you need to restart the kernel
####
from cryspy.util.utility import set_logger # optional
set_logger() # optional
#set_logger(noprint=True, logfile='log_cryspy', errfile='err_cryspy') # write log and err messages to files
from cryspy.RS.gen_struc_RS import gen_pyxtal
nstruc = 10
atype = ('Na', 'Cl')
nat = (4, 4)
mindist = ((2.0, 1.5),
(1.5, 2.0))
spgnum = 'all'
init_struc_data = gen_pyxtal.gen_struc(
nstruc=nstruc,
atype=atype,
nat=nat,
mindist=mindist,
spgnum=spgnum,
)
You can get init_struc_data (dict: {ID: pymatgen Strcture, …})
Structure generation by evolutionary algorithm
Situation: parent A (, parent B) –> child
Prepare two (one) parent structures as pymatgen Structure object.
In this example, just use the results of RS for Cu4Au4 (see, CrySPY utility > notebook > as_library).
import pickle
with open('./Cu4Au4_sample/opt_struc_data.pkl', 'rb') as f:
opt_struc_data = pickle.load(f)
Crossover
from cryspy.EA.gen_struc_EA import crossover
# you can change parent_A and parent_B
parent_A = opt_struc_data[0]
parent_B = opt_struc_data[1]
atype = ('Cu', 'Au')
nat = (4, 4)
mindist = ((1.5, 1.5),
(1.5, 1.5))
child = crossover.gen_child(
atype=atype,
nat=nat,
mindist=mindist,
parent_A=parent_A,
parent_B=parent_B,
)
# child: pymatgen Structure
Permutation
from cryspy.EA.gen_struc_EA import permutation
# you can change parent_A
parent_A = opt_struc_data[0]
atype = ('Cu', 'Au')
nat = (4, 4)
mindist = ((1.5, 1.5),
(1.5, 1.5))
ntimes = 1 # number of times to perform permutatio
child = permutation.gen_child(
atype=atype,
mindist=mindist,
parent_A=parent_A,
ntimes=ntimes,
)
# child: pymatgen Structure
Strain
from cryspy.EA.gen_struc_EA import strain
atype = ('Cu', 'Au')
nat = (4, 4)
mindist = ((1.5, 1.5),
(1.5, 1.5))
sigma_st = 0.05 # standard deviation of strain
child = strain.gen_child(
atype=atype,
mindist=mindist,
parent_A=parent_A,
sigma_st=sigma_st,
)
Situation: parent group, fitness –> children
Data set
Prepare structure and fitness (energy) data as dict. The key is structure ID. In this example, just use the results of RS for Cu4Au4 (see, CrySPY utility > notebook > as_library)..
e.g.
struc_data = {0: (pymatgen Structure), 1: (pymatgen Structure), …}
fitness = {0: 0.019632287242441926, 1: -0.005437509701440302, …}
import pickle
with open('./Cu4Au4_sample/opt_struc_data.pkl', 'rb') as f:
opt_struc_data = pickle.load(f)
with open('./Cu4Au4_sample/rslt_data.pkl', 'rb') as f:
rslt_data = pickle.load(f)
struc_data = opt_struc_data # dict
fitness = rslt_data['E_eV_atom'].to_dict() # you may include None or np.nan for values
Survival of the fittest
from cryspy.EA.survival import survival_fittest
from cryspy.EA.gen_struc_EA.select_parents import SelectParents
from cryspy.EA.gen_struc_EA import crossover, permutation, strain
n_fittest = 5 # number of survivors
ranking, _, _ = survival_fittest(
fitness=fitness,
struc_data=struc_data,
elite_struc=None,
elite_fitness=None,
n_fittest=n_fittest,
fit_reverse=False,
emax_ea=None,
emin_ea=None,
)
# ranking <-- e.g. [2, 1, 0, 7, 9] without structure duplicaiton
Select parents class
sp = SelectParents(ranking) # after set_xxx, we can use sp.get_parents(n_parent)
sp.set_tournament(t_size=2)
Crossover
atype = ('Cu', 'Au')
nat = (4, 4)
mindist = ((1.5, 1.5),
(1.5, 1.5))
n_crsov = 5 # number of structures to be generated by crossover
#id_start = len(init_struc_data) # next Structure ID
id_start = 10
co_children, co_parents, co_operation = crossover.gen_crossover(
atype=atype,
nat=nat,
mindist=mindist,
struc_data=struc_data,
sp=sp,
n_crsov=n_crsov,
id_start=id_start,
)
# co_children <-- dict {ID: pymatgen Structure, ID: pymatgen Structure, ...}
# co_parents <-- e.g. {10: (2, 7), 11: (2, 1), 12: (2, 1), 13: (0, 2), 14: (2, 1)}
# co_operation <-- e.g. {10: 'crossover', 11: 'crossover', ...}
Permutation
n_perm = 5 # number of structures to be generated by permutation
#id_start = len(init_struc_data) + n_crsov # next Structure ID
id_start = 15
ntimes = 1 # number of times to perform permutation
pm_children, pm_parents, pm_operation = permutation.gen_permutation(
atype=atype,
mindist=mindist,
struc_data=struc_data,
sp=sp,
n_perm=n_perm,
id_start=id_start,
ntimes=ntimes,
)
# pm_children <-- dict {ID: pymatgen Structure, ID: pymatgen Structure, ...}
# pm_parents <-- e.g. {15: (2,), 16: (1,), 17: (2,), 18: (1,), 19: (1,)}
# pm_operation <-- e.g. {15: 'permutaion', 16: 'permutation', ...}
Strain
n_strain = 5 # number of structures to be generated by strain
#id_start = len(init_struc_data) + n_crsov + n_perm # next Structure ID
id_start = 20
sigma_st = 0.05 # standard deviation of strain
st_children, st_parents, st_operation = strain.gen_strain(
atype=atype,
mindist=mindist,
struc_data=struc_data,
sp=sp,
n_strain=n_strain,
id_start=id_start,
sigma_st=sigma_st,
)
# st_children <-- dict {ID: pymatgen Structure, ID: pymatgen Structure, ...}
# st_parents <-- e.g. {20: (1,), 21: (2,), 22: (0,), 23: (2,), 24: (2,)}
# st_operation <-- e.g. {20: 'strain', 21: 'strain', ...}