# Customizing cluster spaces¶

Here, we will show how cluster spaces can be customized to construct better CEs for low symmetry systems by introducing local symmetries. We consider a simple binary surface slab and show how orbits can be merged based on physical intuition to reduce the number of parameters.

A more comprehensive tutorial on the subject can be found here.

When analyzing a structure `icet`

uses all available crystal symmetries to determine which clusters are symmetry equivalent and hence belong to the same orbit. This is a rigorous and well defined procedure. For systems of lower symmetry, it can, however, lead to a large number of orbits and hence ECIs. At the same time, one can often still find “local” symmetries in these systems and physical (or chemical) intuition tells us that the parameters associated with such clusters should be very
similar (even if they are not strictly identical).

## A motivating example¶

For illustration consider the construction of a model for a (111) FCC surface. Using `ase`

we can readily construct a 10-layer slab representing such a system and construct a corresponding cluster space.

```
[1]:
```

```
from icet import ClusterSpace
from ase.build import fcc111
structure = fcc111('Au', size=(1, 1, 10), a=4.0, vacuum=10, periodic=True)
# Set up cluster space
cs = ClusterSpace(structure=structure, cutoffs=[3.0], chemical_symbols=['Au', 'Pd'])
display(cs)
```

#### Cluster Space

Field | Value |
---|---|

Space group | P-3m1 (164) |

Sublattice A | ('Au', 'Pd') |

Cutoffs | [3.0] |

Total number of parameters | 16 |

Number of parameters of order 0 | 1 |

Number of parameters of order 1 | 5 |

Number of parameters of order 2 | 10 |

fractional_position_tolerance | 2e-06 |

position_tolerance | 1e-05 |

symprec | 1e-05 |

This cluster space comprises 5 singlets and 10 pairs. For this binary system one thus obtains 15 ECIs including only the zerolet, singlets and nearest neighbour pairs. In practice, one would typically use longer cutoffs and higher orders, quickly leading to a very large number of parameters.

## Inspecting orbits¶

We can print the orbits in order to get information about which sites are included in the representative cluster. Note that, as indicated in the `ClusterSpace`

printout above, the index of the cluster space and the orbit list differ. For a simple binary system, they differ by 1 due since the zerolet is not included in the orbit list. For systems with more than two species, the difference will be more complex due to the inclusion of different multicomponent vectors in the cluster space but not
the orbit list.

We start by inspecting the singlets.

```
[2]:
```

```
for i in range(0, 5):
print(cs.orbit_list[i])
```

```
Order: 1
Multiplicity: 2
Radius: 0.0000
Representative cluster:
Site: 0, Offset: 0 0 0, Position: 0.00 0.00 10.00
Order: 1
Multiplicity: 2
Radius: 0.0000
Representative cluster:
Site: 1, Offset: 0 0 0, Position: 1.41 0.82 12.31
Order: 1
Multiplicity: 2
Radius: 0.0000
Representative cluster:
Site: 2, Offset: 0 0 0, Position: -0.00 1.63 14.62
Order: 1
Multiplicity: 2
Radius: 0.0000
Representative cluster:
Site: 3, Offset: 0 0 0, Position: 0.00 0.00 16.93
Order: 1
Multiplicity: 2
Radius: 0.0000
Representative cluster:
Site: 4, Offset: 0 0 0, Position: 1.41 0.82 19.24
```

From the positions, we find that the first singlet is at the surface (remember the vacuum region), the second is in the subsurface etc., until we reach the middle of the slab for the fifth singlet. We also note that the symmetrically inequivalent sites of the lattice follows the same indexing with e.g. site 0 corresponding to the surface and site 4 to the middle of the slab. There will also be sites 5-9 where e.g. site 5 is equivalent to site 4 and site 9 is equivalent to site 0.

Next, we inspect the pairs. We can print them in the same way, or we can chose to only print the specific property we are interested in, in this case the involved sites.

```
[3]:
```

```
for i in range(5, 15):
print(f'Orbit {i} sites:', cs.orbit_list[i].sites)
```

```
Orbit 5 sites: [4, 5]
Orbit 6 sites: [0, 0]
Orbit 7 sites: [0, 1]
Orbit 8 sites: [1, 1]
Orbit 9 sites: [1, 2]
Orbit 10 sites: [2, 2]
Orbit 11 sites: [2, 3]
Orbit 12 sites: [3, 3]
Orbit 13 sites: [3, 4]
Orbit 14 sites: [4, 4]
```

We find that Orbit 5 is the pair between the two middle layers, Orbit 6 is the in-place surface orbit etc.

Based on physical intuition, we can expect corresponding clusters in the center of the slab to behave nearly identical, i.e., the ECIs associated with, say, the fourth and fifth singlets should be very close if not identical, and similarly for pairs, triplets etc.

## Merging orbits¶

To handle such situations, `icet`

allows one to merge orbits via the `merge_orbits`

function. Which orbits should be merged is entirely up to the user. In the present example, one could for example chose to treat sites 0-1 as surface sites and 2-4 as bulk sites, and merge all orbits (of the same order and radius) consisting of only bulk sites. The following snippet achieves this by merging the singlets corresponding to orbits 2-4 and the pairs corresponding to orbits 5 and 10-14.

```
[4]:
```

```
# The merging information is provided as a dictionary with any of the orbits to merge as the key
cs.merge_orbits({2: [3, 4],
5: [10, 11, 12, 13, 14]})
display(cs)
```

#### Cluster Space

Field | Value |
---|---|

Space group | P-3m1 (164) |

Sublattice A | ('Au', 'Pd') |

Cutoffs | [3.0] |

Total number of parameters | 9 |

Number of parameters of order 0 | 1 |

Number of parameters of order 1 | 3 |

Number of parameters of order 2 | 5 |

fractional_position_tolerance | 2e-06 |

position_tolerance | 1e-05 |

symprec | 1e-05 |

By merging bulk singlet and pair orbits we have cut the number of parameters almost by half, from 16 to 9. The cluster space obtained in this fashion can be used for constructing and sampling cluster expansions in exactly the same way as if no orbits had been merged.