# 4. Creating the Lattice Model
The `LatticeModel` represents the lattice structure on which adsorbates can bind, and supports different lattice types:
- **`default_choice`**: Predefined lattice structures (e.g., triangular, rectangular or hexagonal).
- **`periodic_cell`**: Custom periodic unit cells with specified cell vectors and sites.
- **`explicit`**: Explicitly defined lattice structures (not yet implemented).
#### Allowed lattice types
- `'default_choice'`
- `'periodic_cell'`
- `'explicit'` (Note: As per the current implementation, `'explicit'` is not yet supported.)
---
#### How to create it
There are three primary ways to create a `LatticeModel`, as detailed below.
##### Using a default lattice
This method allows you to select from predefined lattice types and specify basic parameters.
Required parameters:
- **`lattice_type`**: Set to `'default_choice'`.
- **`default_lattice_type`** (`str`): Choose from `'triangular_periodic'`, `'rectangular_periodic'`, or `'hexagonal_periodic'`.
- **`lattice_constant`** (`float`): The lattice constant (Å).
- **`copies`** (`List[int]`): Number of repetitions along the horizontal and vertical directions.
```python
from zacrostools.lattice_model import LatticeModel
lattice_model = LatticeModel(
lattice_type='default_choice',
default_lattice_type='triangular_periodic',
lattice_constant=2.5,
copies=[10, 10]
)
```
##### Defining a custom periodic cell
This method allows you to define a custom lattice by specifying the unit cell vectors, site types, and neighboring structures.
Required parameters:
- **`lattice_type`**: Set to `'periodic_cell'`.
- **`cell_vectors`** (`Tuple[Tuple[float, float], Tuple[float, float]]`): Two vectors defining the unit cell.
- **`sites`** (`Dict[str, Union[Tuple[float, float], List[Tuple[float, float]]]]`): Mapping of site types to their coordinates within the unit cell.
- **`coordinate_type`** (`str`, optional): `'direct'` or `'cartesian'`. Defaults to `'direct'`.
- **`copies`** (`List[int]`): Number of repetitions along the horizontal and vertical directions.
- **`neighboring_structure`** (`Union[str, Dict[str, Union[str, List[str]]]]`): Defines the neighboring relationships between sites.
- If set to `'from_distances'`, you must provide `max_distances`.
- If providing a dictionary, it maps site pairs to a list of relationship keywords.
- **`max_distances`** (`Dict[str, float]`, required if `neighboring_structure='from_distances'`): Defines maximum distances for neighbor pairs.
The following examples show two different ways to create the lattice model for a HfC(001) surface, as described in the image below:
1. Specifying a neighboring structure:
```python
from zacrostools.lattice_model import LatticeModel
# Define cell vectors
cell_vectors = ((3.27, 0.0), (0.0, 3.27))
# Define site positions
sites = {
'tC': [(0.25, 0.25)],
'tM': [(0.75, 0.75)]
}
# Define neighboring structure directly
neighboring_structure = {
'1-2': ['self'],
'1-1': ['north', 'east'],
'2-1': ['north', 'east', 'northeast'],
'2-2': ['north', 'east']
}
# Create the LatticeModel instance
lattice_model = LatticeModel(
lattice_type='periodic_cell',
cell_vectors=cell_vectors,
sites=sites,
coordinate_type='direct',
copies=[10, 10],
neighboring_structure=neighboring_structure
)
```
2. Generating the neighboring structure automatically
```python
from zacrostools.lattice_model import LatticeModel
# Define cell vectors
cell_vectors = ((3.27, 0.0), (0.0, 3.27))
# Define site positions
sites = {
'tC': [(0.25, 0.25)],
'tM': [(0.75, 0.75)]
}
# Define maximum distances for neighbor pairs
max_distances = {
'tC-tC': 3.0,
'tM-tM': 3.0,
'tC-tM': 3.0
}
# Create the LatticeModel instance
lattice_model = LatticeModel(
lattice_type='periodic_cell',
cell_vectors=cell_vectors,
sites=sites,
coordinate_type='direct',
copies=[10, 10],
neighboring_structure='from_distances',
max_distances=max_distances
)
```
##### Loading from an existing lattice input file
This method allows you to create a `LatticeModel` by reading a previously created `lattice_input.dat` file. This is particularly useful when you want to reuse lattice configurations or when the lattice file was provided by another user.
Required parameters:
- **`input_file`** (`str` or `Path`): Path to the existing `lattice_input.dat` file.
```python
from zacrostools.lattice_model import LatticeModel
lattice_model = LatticeModel.from_file(input_file='path/to/lattice_input.dat')
```
Notes for this method:
- It reads the `lattice` block from the file, which starts with the `lattice` keyword and ends with `end_lattice`.
- Supports `'default_choice'` and `'periodic_cell'` lattice types.
- If the lattice type is `'explicit'`, a `LatticeModelError` will be raised as this type is not yet supported.
- Ignores any content outside the `lattice` block.
---
#### Repeating the `LatticeModel`
You can expand the unit cell by repeating it along the cell vectors.
Required parameters:
- **`a`** (`int`): Number of repetitions along the first cell vector.
- **`b`** (`int`): Number of repetitions along the second cell vector.
```python
# Repeat the lattice 2 times along alpha and 3 times along beta
lattice_model.repeat_lattice_model(a=2, b=3)
```
#### Removing a site
You can remove a specific site based on its coordinates.
Required parameters:
- **`direct_coords`** (`Tuple[float, float]`): The direct coordinates of the site to remove.
- **`tolerance`** (`float`, optional): Tolerance for coordinate matching.
```python
# Remove a site at position (0.5, 0.5)
lattice_model.remove_site(direct_coords=(0.5, 0.5))
```
#### Changing the site type
Required parameters:
- **`direct_coords`** (`Tuple[float, float]`): The direct coordinates of the site.
- **`new_site_type`** (`str`): The new site type to assign.
- **`tolerance`** (`float`, optional): Tolerance for coordinate matching.
```python
# Change the site type at position (0.0, 0.0) to 'B'
lattice_model.change_site_type(direct_coords=(0.0, 0.0), new_site_type='B')
```
---
#### Writing the `lattice_input.dat` file
The `LatticeModel` can generate the `lattice_input.dat` file required by Zacros.
Required parameters:
- **`output_dir`** (`str` or `Path`): Directory where the file will be written.
- **`sig_figs`** (`int`, optional): Number of significant figures for numerical values.
```python
# Write the lattice_input.dat file to the specified directory
lattice_model.write_lattice_input(output_dir='kmc_simulation', sig_figs=3)
```
---
#### Full example
This example shows how to create a lattice model for a Pt4 cluster supported on a HfC(001) surface, as described in the image below:
```python
from zacrostools.lattice_model import LatticeModel
# Create a unit cell for PtHfC unit cell from a 4x4 cell of HfC
lattice_model = LatticeModel(
lattice_type='periodic_cell',
cell_vectors=((3.27, 0), (0, 3.27)),
sites={'tC': (0.25, 0.25), 'tM': (0.75, 0.75)},
copies=[10, 10],
neighboring_structure='from_distances',
max_distances={'tC-tC': 4.0, 'tC-tM': 4.0, 'tM-tM': 4.0, 'Pt-Pt': 4.0, 'Pt-tC': 4.0, 'Pt-tM': 4.0},
)
lattice_model.repeat_lattice_model(4, 4)
# Replace four tC sites by Pt sites
for coordinates in [(0.3125, 0.3125), (0.3125, 0.5625), (0.5625, 0.3125), (0.5625, 0.5625)]:
lattice_model.change_site_type(direct_coords=coordinates, new_site_type='Pt')
# Remove the tM site in the middle of the four Pt sites
lattice_model.remove_site(direct_coords=(0.4375, 0.4375))
# Define the number of copies of the unit cell for the simulation
lattice_model.copies = [3, 3]
# Write the lattice_input.dat file in a folder named 'PtHfC'
lattice_model.write_lattice_input(output_dir='PtHfC')
```
---