Skip to content

Commit 86069dc

Browse files
committed
35 proposal make failed generate output structures (#36)
* Update ignore list * Swap order of placement list * Fix shuffle for both dimensions * Improve error handling * Add procedures to remove atoms * Change void placement grid handling * Update generate error handling and structure output * Add calculator option * Add example host structures * Update tutorials * Update learning scripts * Fix unit tests * Fix indentation * Fix indentation
1 parent 087c494 commit 86069dc

34 files changed

+890
-206
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,5 @@ DVASP_MACE_comparison/
5050
pca_model*.pkl
5151
.benchmarks/
5252
.local-pre-commit-config.yaml
53-
*.tgz
53+
*.tgz
54+
.ipynb_checkpoints

app/inputs.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ subroutine set_global_vars()
126126
write(0,'("&
127127
&ERROR: No input filename supplied, &
128128
&but the flag ''-f'' was used&
129-
&")')
129+
&")')
130130
infilename_do: do j = 1, 3
131131
write(6,'("Please supply an input filename:")')
132132
read(5,'(A)') input_file
@@ -157,7 +157,7 @@ subroutine set_global_vars()
157157
write(6,'("-----------------FILE-NAME-FLAGS-----------------")')
158158
write(6,'(2X,"-f<STR> : Input structure file name (&
159159
&Default = (empty)&
160-
&).")')
160+
&).")')
161161
stop
162162
end if
163163
end do flagloop

docs/source/index.rst

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ An example
1515

1616
.. code-block:: python
1717
18-
# A simple example of how to use RAFFLE to generate 10 structures of diamond
18+
# A simple example of how to use RAFFLE to generate 10 structures of diamond and write them to a single file
1919
from ase import Atoms
20+
from ase.io import write
21+
from ase.calculators.singlepoint import SinglePointCalculator
2022
from raffle.generator import raffle_generator
2123
from mace.calculators import mace_mp
2224
@@ -41,6 +43,16 @@ An example
4143
generator.distributions.update(structures[num_structures_old:])
4244
num_structures_old = len(structures)
4345
46+
structures = generator.get_structures(calc)
47+
for structure in structures:
48+
structure.calc = SinglePointCalculator(
49+
structure,
50+
energy=structure.get_potential_energy(),
51+
forces=structure.get_forces()
52+
)
53+
54+
write('structures.traj', structures)
55+
4456
.. toctree::
4557
:maxdepth: 3
4658
:caption: Contents:

docs/source/tutorials/BaTiO3_tutorial.rst

Lines changed: 0 additions & 5 deletions
This file was deleted.

docs/source/tutorials/C-MgO_tutorial.rst

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
.. si-ge:
2+
3+
========================
4+
Si|Ge interface tutorial
5+
========================
6+
7+
This tutorial will guide you through the process of performing RAFFLE-based structure search for an Si|Ge interface.
8+
9+
The tutorial is designed to show how a RAFFLE generator given no prior knowledge can learn bonding and statistically available interface configurations.
10+
Statistically available configurations are those that are likely to exist due to energetic values close to the ground state, within thermal and entropy conditions.
11+
12+
The example script can be found in the following directory:
13+
14+
.. code-block:: bash
15+
16+
raffle/example/python_pkg/Si-Ge_learn/learn.py
17+
18+
We recommend reading through the file and running it to understand the process of learning and generating structures.
19+
However, we will provide a brief overview of the script here.
20+
21+
First, we must import the required packages:
22+
23+
.. code-block:: python
24+
25+
from ase import Atoms
26+
from raffle.generator import raffle_generator
27+
from mace.calculators import mace_mp
28+
import numpy as np
29+
30+
Next, we need to set up the RAFFLE generator and the calculator to calculate the energies of the structures.
31+
In this example, we use the CHGNet calculator:
32+
33+
.. code-block:: python
34+
35+
generator = raffle_generator()
36+
37+
calc = mace_mp(model="mace-mpa-0-medium.model")
38+
39+
Note, choice of calculator is important.
40+
The calculator should be valid within and near the chemical environment of the structures being generated; in this case, Si and Ge bonding.
41+
If this is the case, it can accurately identify local minima and provide a good representation of the energy landscape.
42+
For this example, we use the [MACE-MPA-0 calculator](https://github.com/ACEsuit/mace-mp/releases/tag/mace_mpa_0), which, from preliminary testing, has been found to be suitable for Si and Ge bonding.
43+
To use the MACE-MPA-0 calculator, you will need to download the model file from the link provided and place it in the same directory as the script (and install the MACE package using `pip install mace-torch`, version 0.3.10 or later).
44+
The CHGNet calculator was not found to be suitable for Si and Ge interface bonding.
45+
46+
Then, we need to create the host structure.
47+
Here, an abrupt Si|Ge interface is generated.
48+
This is the base structure that will be added to in order to generate the structures.
49+
A vacuum region of 5.54 Å is set up between the Si and Ge regions, in which the atoms will be placed by RAFFLE.
50+
51+
.. code-block:: python
52+
53+
Si_bulk = build.bulk("Si", crystalstructure="diamond", a=5.43)
54+
Si_cubic = build.make_supercell(Si_bulk, [[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
55+
Ge_bulk = build.bulk("Ge", crystalstructure="diamond", a=5.65)
56+
Ge_cubic = build.make_supercell(Ge_bulk, [[-1, 1, 1], [1, -1, 1], [1, 1, -1]])
57+
58+
Si_supercell = build.make_supercell(Si_cubic, [[2, 0, 0], [0, 2, 0], [0, 0, 1]])
59+
Ge_supercell = build.make_supercell(Ge_cubic, [[2, 0, 0], [0, 2, 0], [0, 0, 1]])
60+
61+
Si_surface = build.surface(Si_supercell, indices=(0, 0, 1), layers=2)
62+
Ge_surface = build.surface(Ge_supercell, indices=(0, 0, 1), layers=2)
63+
64+
host = build.stack(Si_surface, Ge_surface, axis=2, distance= 5.43/2 + 5.65/2)
65+
cell[2, 2] -= 3.8865
66+
host.set_cell(cell, scale_atoms=False)
67+
68+
69+
The script then sets parameters for the generator and provides an initial database.
70+
Note, this database only contains prior information of Si-Si and Ge-Ge bonding, and no information about Si-Ge bonding.
71+
This is to demonstrate the ability of RAFFLE to learn from scratch.
72+
73+
.. code-block:: python
74+
75+
Si_bulk.calc = calc
76+
Ge_bulk.calc = calc
77+
generator.distributions.set_element_energies(
78+
{
79+
'Si': Si_bulk.get_potential_energy() / len(Si_bulk),
80+
'Ge': Ge_bulk.get_potential_energy() / len(Ge_bulk),
81+
}
82+
)
83+
84+
# set energy scale
85+
generator.distributions.set_kBT(0.2)
86+
87+
# set the distribution function widths (2-body, 3-body, 4-body)
88+
generator.distributions.set_width([0.04, np.pi/160.0, np.pi/160.0])
89+
90+
# set the initial database
91+
initial_database = [Si_bulk, Ge_bulk]
92+
generator.distributions.create(initial_database)
93+
94+
Finally, the script generates structures using the generator.
95+
The generator is given the host structures.
96+
Finally, the generator is run for each host structure, providing a unique stoichiometry each time and using a custom method ratio.
97+
The
98+
99+
.. code-block:: python
100+
101+
generator.set_host(host)
102+
generator.set_bounds([[0, 0, 0.34], [1, 1, 0.52]])
103+
for iter in range(40):
104+
# generate the structures
105+
structures, exit_code = generator.generate(
106+
num_structures = 5,
107+
stoichiometry = { 'Si': 16, 'Ge': 16 },
108+
seed = iter,
109+
method_ratio = {"void": 0.1, "rand": 0.01, "walk": 0.25, "grow": 0.25, "min": 1.0},
110+
verbose = 0,
111+
calc = calc
112+
)
113+
generator.distributions.update(structures)
114+
115+
structures = generator.get_structures()
116+
write('structures.traj', structures)
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
.. aluminium:
2+
3+
==================
4+
Aluminium tutorial
5+
==================
6+
7+
This tutorial will guide you through the process of performing RAFFLE-based structure search for the bulk phases of aluminium.
8+
9+
The tutorial is designed to show how a RAFFLE generator given no prior knowledge can learn bonding and identify known phases.
10+
This is not an expected use-case of RAFFLE due to its application to a bulk system, but still demonstrates the expected workflow and capabilities.
11+
12+
The example script can be found in the following directory:
13+
14+
.. code-block:: bash
15+
16+
raffle/example/python_pkg/Al_learn/learn.py
17+
18+
We recommend reading through the file and running it to understand the process of learning and generating structures.
19+
However, we will provide a brief overview of the script here.
20+
21+
First, we must import the required packages:
22+
23+
.. code-block:: python
24+
25+
from ase import Atoms
26+
from raffle.generator import raffle_generator
27+
from chgnet.model import CHGNetCalculator
28+
import numpy as np
29+
30+
Next, we need to set up the RAFFLE generator and the calculator to calculate the energies of the structures.
31+
In this example, we use the CHGNet calculator:
32+
33+
.. code-block:: python
34+
35+
generator = raffle_generator()
36+
37+
calc = CHGNetCalculator()
38+
39+
Then, we need to create the host structure.
40+
Here, a set of host cells are generated to represent the multiple potential bulk phases of aluminium.
41+
These are then used to generate the structures.
42+
43+
.. code-block:: python
44+
45+
crystal_structures = ['orthorhombic', 'hcp']
46+
hosts = []
47+
for crystal_structure in crystal_structures:
48+
for a in np.linspace(3.1, 5.4, num=6):
49+
atom = build.bulk(
50+
name = 'Al',
51+
crystalstructure = crystal_structure,
52+
a = a, b = a, c = a,
53+
)
54+
hosts.append(Atoms(
55+
'Al',
56+
positions = [(0, 0, 0)],
57+
cell = atom.get_cell(),
58+
pbc = True,
59+
calculator = calc
60+
))
61+
62+
The script then sets parameters for the generator and provides an initial database.
63+
Note, this database is effectively empty, as it only contains a single structure, which is an isolated aluminium atom.
64+
65+
.. code-block:: python
66+
67+
initial_database = [Atoms('Al', positions=[(0, 0, 0)], cell=[8, 8, 8], pbc=True)]
68+
initial_database[0].calc = calc
69+
generator.distributions.create(initial_database)
70+
71+
Finally, the script generates structures using the generator.
72+
The generator is given the host structures.
73+
Finally, the generator is run for each host structure, providing a unique stoichiometry each time and using a custom method ratio.
74+
75+
.. code-block:: python
76+
77+
for host in hosts:
78+
generator.set_host(host)
79+
generator.generate(
80+
num_structures = 5,
81+
stoichiometry = { 'Al': num_atoms },
82+
method_ratio = {"void": 0.5, "rand": 0.001, "walk": 0.5, "grow": 0.0, "min": 1.0},
83+
)
84+
85+
structures = generator.get_structures()
86+
write('structures.traj', structures)

docs/source/tutorials/diamond_tutorial.rst

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ This is the base structure that will be added to in order to generate the struct
6161
3.5607451090903233, 3.5607451090903233, 7.1214902182
6262
], pbc=True
6363
)
64-
)
6564
6665
host.calc = calc
6766
generator.set_host(host)
@@ -121,12 +120,12 @@ We are now ready to generate structures using the database of structures.
121120
.. code-block:: python
122121
123122
num_structures_old = 0
124-
generator.generate(
123+
structures, exit_code = generator.generate(
125124
num_structures = 1,
126125
stoichiometry = { 'C': 8 },
127126
method_ratio = {"void":0.0001, "min":1.0},
127+
calc = calc
128128
)
129-
structures = generator.get_structures(calc)
130129
131130
We should now have a structure of diamond.
132131
This structure can be visualised using the ASE package.

0 commit comments

Comments
 (0)