Skip to content

Commit bfbb786

Browse files
committed
Update AGOX examples
1 parent d766cf0 commit bfbb786

1,028 files changed

Lines changed: 698 additions & 103510 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

example/python_pkg/C_learn/DRSS/pca.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@
276276
"outputs": [],
277277
"source": [
278278
"# get the DRAFFLE relaxed structures and energies\n",
279-
"raffle_rlxd_structures = read(\"../DRAFFLE/DResponse/rlxd_structures_seed0.traj\", index=\":\")\n",
279+
"raffle_rlxd_structures = read(\"../DRAFFLE/DOutput/rlxd_structures_seed0.traj\", index=\":\")\n",
280280
"raffle_energies_per_atom = [structure.get_potential_energy() / len(structure) for structure in raffle_rlxd_structures]\n",
281281
"raffle_delta_en_per_atom = np.array(raffle_energies_per_atom) - min_energy"
282282
]
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import matplotlib
2+
3+
matplotlib.use("Agg")
4+
5+
from agox import AGOX
6+
from agox.databases import Database
7+
from agox.environments import Environment
8+
from agox.evaluators import LocalOptimizationEvaluator
9+
import shephex
10+
from ase import build
11+
12+
@shephex.chain()
13+
def raffle_agox(index=42, void=0.1, rand=0.01, walk=0.25, grow=0.25, min=1.0):
14+
15+
16+
# Using argparse if e.g. using array-jobs on Slurm to do several independent searches.
17+
# from argparse import ArgumentParser
18+
# parser = ArgumentParser()
19+
# parser.add_argument('-i', '--run_idx', type=int, default=0)
20+
# args = parser.parse_args()
21+
22+
##############################################################################
23+
# System & generator settings:
24+
##############################################################################
25+
26+
import numpy as np
27+
from agox.generators.raffle import RaffleGenerator, bounds_to_confinement
28+
# from mace.calculators import mace_mp
29+
from agox.utils.replica_exchange.priors import get_prior
30+
from ase.io import read
31+
32+
## Set seed and database-index
33+
seed = index
34+
database_index = index
35+
np.random.seed(seed)
36+
37+
## Set up the MACE calculator
38+
mace = get_prior("mace-mpa")
39+
# calc_params = { 'model': '/FULL/PATH/TO/MODEL/FILE' }
40+
# mace = mace_mp(**calc_params)
41+
42+
## Set up the method ratio dictionary and generate a unique ID
43+
method_ratio = {
44+
"void": void,
45+
"rand": rand,
46+
"walk": walk,
47+
"grow": grow,
48+
"min": min
49+
}
50+
method_id = "_".join(f"{k}{v:g}" for k, v in sorted(method_ratio.items()))
51+
print("method ratio:", method_ratio)
52+
print("method_id:", method_id)
53+
54+
## Set up the host structure (CHANGE THIS TO YOUR HOST STRUCTURE LOCATION)
55+
template = read('${HOME}/DAGOX/DSiGe/host.traj')
56+
template.calc = mace
57+
template.set_pbc(True)
58+
59+
## Set up the reference energies for Si and Ge
60+
Si_bulk = build.bulk("Si", crystalstructure="diamond", a=5.43)
61+
Si_bulk.calc = mace
62+
Si_reference_energy = Si_bulk.get_potential_energy() / len(Si_bulk)
63+
Ge_bulk = build.bulk("Ge", crystalstructure="diamond", a=5.65)
64+
Ge_bulk.calc = mace
65+
Ge_reference_energy = Ge_bulk.get_potential_energy() / len(Ge_bulk)
66+
67+
element_energies = {'Si': Si_reference_energy, 'Ge': Ge_reference_energy}
68+
print("element reference energies:", element_energies)
69+
70+
## Set up the species to place in the host structure
71+
species_to_place={'Si' : 16, 'Ge': 16}
72+
symbols = ""
73+
for key in species_to_place.keys():
74+
symbols += key
75+
symbols += str(species_to_place[key])
76+
77+
## Set up the bounding box for the confinement
78+
confinement_corner, confinement_cell = bounds_to_confinement([[0, 0, 0.34], [1, 1, 0.52]],template)
79+
80+
## Set up the environment
81+
environment = Environment(
82+
template=template,
83+
symbols=symbols,
84+
confinement_cell=confinement_cell,
85+
confinement_corner=confinement_corner,
86+
fix_template = False,
87+
)
88+
89+
## Database
90+
db_path = f"../db{database_index}_{method_id}.db" # From input argument!
91+
database = Database(filename=db_path, order=5)
92+
database.restore_to_memory()
93+
94+
## Set up the RaffleGenerator
95+
generator = RaffleGenerator(
96+
**environment.get_confinement(),
97+
host=template,
98+
database=database,
99+
environment=environment,
100+
species=species_to_place,
101+
element_energies=element_energies,
102+
transfer_data=[Si_bulk,Ge_bulk],
103+
order=1,
104+
width=[0.04, np.pi/160.0, np.pi/160.0],
105+
kBT=0.2,
106+
n_structures=5,
107+
from_host=False,
108+
sampler=None,
109+
train=True,
110+
seed=seed,
111+
method_ratio = method_ratio
112+
)
113+
114+
##############################################################################
115+
# Structural optimisation settings:
116+
##############################################################################
117+
118+
## Set up the structural optimisation evaluator (defaults to ASE's BFGS optimizer)
119+
# from ase.optimize import FIRE # Uncomment to use FIRE instead of BFGS
120+
evaluator = LocalOptimizationEvaluator(
121+
mace,
122+
# optimizer = FIRE, # Uncomment to use FIRE instead of BFGS
123+
gets={"get_key": "candidates"},
124+
store_trajectory=False,
125+
optimizer_run_kwargs={"fmax": 0.05, "steps": 200},
126+
order=3,
127+
number_to_evaluate=5,
128+
constraints=environment.get_constraints(),
129+
fix_template = False,
130+
)
131+
132+
## Set up post-processors to filter the generated structures.
133+
# This checks the minimum distance between atoms in the generated structures.
134+
from agox.postprocessors.minimum_dist import MinimumDistPostProcess
135+
c1 = 0.6
136+
c2 = 5
137+
minimum_dist = MinimumDistPostProcess(
138+
c1=c1,
139+
c2=c2,
140+
order=1.5,
141+
)
142+
minimum_dist2 = MinimumDistPostProcess(
143+
c1=c1,
144+
gets = {"get_key" : "evaluated_candidates"},
145+
sets = {"set_key" : "evaluated_candidates"},
146+
c2=c2,
147+
order=3.5,
148+
)
149+
150+
##############################################################################
151+
# Set up and run the AGOX search:
152+
##############################################################################
153+
154+
## Set up the AGOX search workflow
155+
agox = AGOX(generator, minimum_dist, minimum_dist2, database, evaluator, seed=seed)
156+
157+
## Run the AGOX search for N_iterations
158+
agox.run(N_iterations=40)
159+
160+
161+
162+
if __name__ == "__main__":
163+
164+
walkers = 16
165+
166+
## Set up the experiments to run
167+
# This is an example of how to set up a series of experiments with different
168+
# method ratios and different seeds.
169+
experiments = (raffle_agox(directory='method_ratio/').
170+
zip(void=[1.0, 0.1, 0.1]).
171+
zip(rand=[0.1, 0.01, 0.1]).
172+
zip(walk=[0.5, 0.25, 0.5]).
173+
zip(grow=[0.5, 0.25, 0.5]).
174+
zip(min =[1.0, 1.0, 1.0]).
175+
permute(index=range(10))
176+
)
177+
178+
## Uncomment for Slurm execution
179+
executor = shephex.executor.SlurmExecutor.from_profile(
180+
'basic',
181+
safety_check=False,
182+
time="09:00:00",
183+
ntasks_per_node=walkers,
184+
cpus_per_task=8,
185+
)
186+
187+
# ## Uncomment for local execution
188+
# executor = shephex.executor.LocalExecutor()
189+
190+
# Submit the experiments to the executor
191+
executor.execute(experiments)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# This script tidies up the n-body database files by organizing them into subdirectories based on the number of bodies.
2+
# By running this script, then the following agox line in the command line:
3+
# agox analysis method_ratios/*
4+
# you will get analysis of the success split up by the method ratios used in the generation of the structures.
5+
6+
import os
7+
import re
8+
import shutil
9+
from math import gcd
10+
from functools import reduce
11+
12+
src_dir = "method_ratio"
13+
dst_base = "method_ratios"
14+
15+
# Regex to match the filename pattern
16+
pattern = re.compile(
17+
r"^db(?P<seed>\d+)_dist_grow(?P<grow>[\d\.]+)_min(?P<min>[\d\.]+)_rand(?P<rand>[\d\.]+)_void(?P<void>[\d\.]+)_walk(?P<walk>[\d\.]+)\.db$"
18+
)
19+
20+
def float_str_to_int_ratios(values):
21+
# Convert all to floats
22+
floats = [float(v) for v in values]
23+
scale = 1000 # To avoid float precision issues
24+
ints = [round(f * scale) for f in floats]
25+
divisor = reduce(gcd, ints)
26+
return [i // divisor for i in ints]
27+
28+
os.makedirs(dst_base, exist_ok=True)
29+
30+
for fname in os.listdir(src_dir):
31+
match = pattern.match(fname)
32+
if match:
33+
parts = match.groupdict()
34+
ratios = float_str_to_int_ratios([
35+
parts["void"], parts["rand"], parts["walk"], parts["grow"], parts["min"]
36+
])
37+
# Assign to the appropriate method
38+
v, r, w, g, m = ratios
39+
# exit()
40+
subdir_name = f"v{v}_r{r}_w{w}_g{g}_m{m}"
41+
fname_new = f"db{parts['seed']}.db" #_{subdir_name}.db"
42+
subdir_path = os.path.join(dst_base, subdir_name)
43+
os.makedirs(subdir_path, exist_ok=True)
44+
45+
src_path = os.path.join(src_dir, fname)
46+
dst_path = os.path.join(subdir_path, fname_new)
47+
shutil.copy2(src_path, dst_path)

0 commit comments

Comments
 (0)