Commit ac1916cb by Malthe Kjær Bisbo

### added EMT tutorial, including tutorial on constrining free atoms during search

parent 9588e095
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
 import numpy as np from ase.build import fcc111 from ase.constraints import FixAtoms from ase.calculators.emt import EMT from gofee.candidates import CandidateGenerator, StartGenerator, RattleMutation, PermutationMutation from gofee.utils import OperationConstraint from gofee import GOFEE ### Define calculator ### calc = EMT() ### Set up system ### # 1-layer fixed Cu(111) slab template = fcc111('Cu', size=(5, 5, 1), vacuum=10.0) c = FixAtoms(indices=np.arange(len(template))) template.set_constraint(c) # Stoichiometry of atoms to be placed stoichiometry = 7*[79] ## Box for startgenerator and rattle-mutation k = 0.2 # Shrinkage fraction from each side of the box in v[0] and v[1] directions. cell = template.get_cell() # Initialize box with cell v = np.copy(cell) # Set height of box v[2][2] = 5 # Shrink box in v[0] and v[1] directions v[0] *= (1-2*k) v[1] *= (1-2*k) # Chose anker point p0 so box in centered in v[0] and v[1] directions. z_max_slab = np.max(template.get_positions()[:,2]) p0 = np.array((0, 0, z_max_slab+0.3)) + k*(cell[0]+cell[1]) # Make box box = [p0, v] # initialize startgenerator (used to generate initial structures) sg = StartGenerator(template, stoichiometry, box) ### Set up candidate generation operations ### # Set up constraint for rattle-mutation box_constraint = OperationConstraint(box=box) # initialize rattle-mutation n_to_optimize = len(stoichiometry) rattle = RattleMutation(n_to_optimize, Nrattle=2, rattle_range=4) candidate_generator = CandidateGenerator([0.2, 0.8], [sg, rattle]) ### Initialize and run search ### search = GOFEE(calc=calc, startgenerator=sg, candidate_generator=candidate_generator, max_steps=150, population_size=5, position_constraint=box_constraint) search.run() \ No newline at end of file
 import numpy as np from ase import Atoms from ase.calculators.emt import EMT from gofee.candidates import CandidateGenerator, StartGenerator, RattleMutation from gofee import GOFEE ### Define calculator ### calc = EMT() ### Set up system ### # make empty cell template = Atoms('', cell=[20,20,20], pbc=[0, 0, 0]) # Stoichiometry of atoms to be placed stoichiometry = 15*[29] # Box in which to place atoms randomly v = 5*np.eye(3) p0 = np.array((7.5, 7.5, 7.5)) box = [p0, v] # initialize startgenerator (used to generate initial structures) sg = StartGenerator(template, stoichiometry, box) ### Set up candidate generation operations ### # initialize rattle mutation n_to_optimize = len(stoichiometry) rattle = RattleMutation(n_to_optimize, Nrattle=3, rattle_range=4) candidate_generator = CandidateGenerator(probabilities=[0.2, 0.8], operations=[sg, rattle]) ### Initialize and run search ### search = GOFEE(calc=calc, startgenerator=sg, candidate_generator=candidate_generator, max_steps=60, population_size=5) search.run() \ No newline at end of file
 ... ... @@ -11,3 +11,62 @@ In this search we will utilize an :class:`OperationConstraint` to constraint the :class:`RattleMutation` to only rattle the atoms within a certain box in space that we define. The following script :download:`Au7_on_Cu111.py` is used to carry out the constrainted search: .. literalinclude:: Au7_on_Cu111.py If ASE and GPAW are set up and sourced propperly, you can run the code as:: mpiexec --mca mpi_warn_on_fork 0 gpaw-python Au7_on_Cu111.py What follows is a description of the elements of the python code above, which relates to consraining the atomix position during the search. Box setup --------- As previously in the :ref:`Cu15 cluster search `, we define a box in which initial atoms are placed. In this example we will also use this box to constrain the position of the "free" atoms during the search. Defining a box positioned 0.3Å above the slab, with a height of 5Å and with xy-dimensions shrunk, from all sides by a fraction "k", relative to the cell xy-dimensions, can be achieved by:: ## Box for startgenerator and rattle-mutation k = 0.2 # Shrinkage fraction from each side of the box in v[0] and v[1] directions. cell = template.get_cell() # Initialize box with cell v = np.copy(cell) # Set height of box v[2][2] = 5 # Shrink box in v[0] and v[1] directions v[0] *= (1-2*k) v[1] *= (1-2*k) # Chose anker point p0 so box in centered in v[0] and v[1] directions. z_max_slab = np.max(template.get_positions()[:,2]) p0 = np.array((0, 0, z_max_slab+0.3)) + k*(cell[0]+cell[1]) # Make box box = [p0, v] Constraint object ----------------- The constrraint object is made using:: from gofee.utils import OperationConstraint box_constraint = OperationConstraint(box=box) Initialize constrained GOFEE search ----------------------------------- The constrained GOFEE search is initialized using the ``position_constraint`` keyword:: from gofee import GOFEE search = GOFEE(calc=calc, startgenerator=sg, candidate_generator=candidate_generator, max_steps=150, population_size=5, position_constraint=box_constraint) \ No newline at end of file
 .. _cu_cluster_search: ============= Cu15 with EMT ============= In this tutorial we carry out a search for isolated Cu15-clusters described by the EMT potential for efficiency. The following script :download:`Cu15.py` is used to carry out the search (the indivitual elements of the code are explainted further below): .. literalinclude:: Cu15.py If ASE and GPAW are set up and sourced propperly, you can run the code as:: mpiexec --mca mpi_warn_on_fork 0 gpaw-python Cu15.py What follows is a description of the python script above. Setting up the system ===================== An important prerequisite for starting a search is to set up the system. This is done by defining a template and a stoichiometry of the atoms to optimize. The *template* is an :class:`Atoms` object, either describing an empty cell or a cell containing for example a slab of atoms. For most purposes, the atoms in the template shold be fixed using the :class:`ase.constraints.FixAtoms` constraint, as the template atoms are kept fixed during mutation operation, but will take part in surrogate-relaxation if not fixed. In this example the template is taken to be an empty 20Åx20Åx20Å cell, since we considder isolated Cu-clusters. The code to generate the template is:: from ase import Atoms template = Atoms('', cell=[20,20,20], pbc=[0, 0, 0]) The *stoichiometry* of atoms to optimize is a list of atomic numbers. In this case 15 copper atoms (atomic nymber 29):: stoichiometry = 15*[29] Startgenerater - for making initial structures ============================================== To initialize the search, initial structures need to be generated. This is carried out using the :class:`StartGenerator`, which in addition to the *template* and *stoichiometry* defined above, need a *box* in which to randomly place the atoms defined in the *stoichiometry*. The *box* is naturally defined by a point *p0* and three spanning vectors going out from that point. These are defined bu the 3x3 matrix *v* in the example. In the example a 20Åx20Åx20Å square box in the center of the cell is used:: import numpy as np v = 5*np.eye(3) p0 = np.array((7.5, 7.5, 7.5)) box = [p0, v] The *startgenerator* can then be initialized with the code:: from gofee.candidates import StartGenerator sg = StartGenerator(template, stoichiometry, box) CandidateGenerator ================== In GOFEE, the configurational space is explored by generation new candidate structures. New candidates can be either completely random structures made using the *startgenerator* or they can be the result of applying mutation operations to a population of some of the best structures visited during the search. Examples of mutaion operations are the :class:`RattleMutation`, which randomly shifts some of the atoms and the :class:`PermutaionMutation` which randomly permutes some atoms of different type. In this example we only optimize atoms of a single type, and therfor only use the :class:`RattleMutation`, initializing it to rattle on average Natoms=3 atoms a maximum distance of rattle_range=4Å, is achieved with:: from gofee.candidates import RattleMutation n_to_optimize = len(stoichiometry) rattle = RattleMutation(n_to_optimize, Nrattle=3, rattle_range=4) Given some of the above described operations. e.g. a :class:`StartGenerator` and a :class:`RattleMutation`, one can initialize a :class:`CandidateGenerator`, which handles the generation of new candidates by applying the supplied *operations* with probability specified in the *probabilities* list. A CandidateGenerator which uses the startgenerator *sg* with 20% probability and the rattle operation *rattle* with 80% probability, is initialized as follows:: from gofee.candidates import CandidateGenerator candidate_generator = CandidateGenerator(probabilities=[0.2, 0.8], operations=[sg, rattle]) Initialize and run GOFEE ======================== With all the above objects defined, we are ready to initialize and run GOFEE. To run the search for 60 iterations with a population size of 5, use:: from gofee import GOFEE search = GOFEE(calc=calc, startgenerator=sg, candidate_generator=candidate_generator, max_steps=60, population_size=5) search.run() This tutorial relies on many default settings of GOFEE, which could be changed. To see how these settings are changed, have a look at the other tutorials.
 .. _modify_gpr: ========================= Modifying surrogate model ========================= This tutorial extends the previous one for TiO clusters, :ref:`searching for TiO clusters `. It is This tutorial extends the previous one for :ref:`Cu15 clusters `. It is therefore recomended that you do that one before the present one. In the avove mentioned tutorial GOFEE was initialized with the following arguments:: from gofee import GOFEE search = GOFEE(calc=calc, startgenerator=sg, candidate_generator=candidate_generator, max_steps=100, max_steps=60, population_size=5) however GOFEE takes a number of other arguments, including a ... ... @@ -20,19 +23,19 @@ Gaussian Process regression (GPR) model, which is actively learned during the search and used for cheap optimization of new candidates. One can for example apply a GPR model with another degree of regularization in the search. As the regularization is a parameter of the *kernel*, passed to the GPR model, the code will look like this:: in the search. This is controlled by the ``noise`` parameter of the ``kernel``, passed to the GPR model. The modification can be achieved by:: from gofee.surrogate.gpr import GPR from gofee.surrogate.kernel import double_gauss_kernel from gofee.surrogate import GPR from gofee.surrogate.kernel import DoubleGaussKernel kernel = double_gauss_kernel(noise=1e-6) kernel = DoubleGaussKernel(noise=1e-6) gpr = GPR(kernel=kernel) search = GOFEE(calc=calc, gpr=gpr, startgenerator=sg, candidate_generator=candidate_generator, max_steps=100, max_steps=60, population_size=5)
 ... ... @@ -53,5 +53,5 @@ Then define the *box* within which the :class:`StartGenerator` places atoms rand Finally the :class:`StartGenerator` can be initialized:: from candidate_operations.candidate_generation import StartGenerator from gofee.candidates import StartGenerator sg = StartGenerator(slab, stoichiometry, box) \ No newline at end of file
 ... ... @@ -9,6 +9,16 @@ This is the turorial for the GOFEE structure search. .. toctree:: :maxdepth: 1 cu_clusters/cu_clusters au_on_cu/au_on_cu modifying_surrogate_model/modifying_surrogate_model tio_clusters/tio_clusters tio2_reconstruction/tio2_reconstruction modifying_surrogate_model/modifying_surrogate_model \ No newline at end of file Different types of searches/modifications covered in these tutorials include: * Isolated clusters (see :ref:`here `) * Constraining the positions of the free atoms during the search (see :ref:`here `) * Surface reconstruction (see :ref:`here `) * Modifying the surrogate model (see :ref:`here `)
No preview for this file type
 ... ... @@ -34,7 +34,9 @@ ... ... @@ -78,11 +80,23 @@
... ... @@ -129,6 +143,8 @@
• Docs »
• Tutorial »
• Au7 in Cu(111) with EMT
• ... ... @@ -155,6 +171,126 @@ the Cu(111) surface.

In this search we will utilize an OperationConstraint to constraint the RattleMutation to only rattle the atoms within a certain box in space that we define.

The following script Au7_on_Cu111.py is used to carry out the constrainted search:

import numpy as np

from ase.build import fcc111
from ase.constraints import FixAtoms
from ase.calculators.emt import EMT

from gofee.candidates import CandidateGenerator, StartGenerator, RattleMutation, PermutationMutation
from gofee.utils import OperationConstraint
from gofee import GOFEE

### Define calculator ###
calc = EMT()

### Set up system ###
# 1-layer fixed Cu(111) slab
template = fcc111('Cu', size=(5, 5, 1), vacuum=10.0)
c = FixAtoms(indices=np.arange(len(template)))
template.set_constraint(c)

# Stoichiometry of atoms to be placed
stoichiometry = 7*[79]

## Box for startgenerator and rattle-mutation
k = 0.2  # Shrinkage fraction from each side of the box in v[0] and v[1] directions.
cell = template.get_cell()
# Initialize box with cell
v = np.copy(cell)
# Set height of box
v[2][2] = 5
# Shrink box in v[0] and v[1] directions
v