-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6a13870
Showing
3 changed files
with
110 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# perovskites-oct-distortions | ||
Collection of python functions useful to manipulate the structures of hybrid organic/inorganic perovskites. | ||
Main directory contains: | ||
- `rotations.py` : functions to apply random rotations to the organic molecules occupiying the A site in your perovskite. Useful to break symmetries, avoid the polar parallel arrangement (if your cation has a dipole moment, e.g. formamdinium) | ||
- folder `octahedral_distortions`: hosts the file `oct_distortions.py`. This contains the function `get_tilting_angles`, which calculates the average of the Pb-I-Pb angles in your structure. Values close to 180º indicate small tilting while angles deviating from 180º point towards significant tilting of the octahedra. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2022 Laboratory of Computational Chemistry and Biochemistry - EPFL | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
# Funtions to rotate the molecules in the A cation position, useful to avoid all molecules being parallel | ||
import random | ||
from copy import deepcopy | ||
from pymatgen.core.structure import Structure | ||
import numpy as np | ||
|
||
def get_center_of_mass( | ||
structure: Structure, | ||
sites_indexes: list | ||
) -> np.array: | ||
""" | ||
Calculates center of mass for sites specified as sites_indexes | ||
""" | ||
center = np.zeros(3) | ||
total_weight= 0 | ||
for index in sites_indexes: | ||
site = structure[index] | ||
wt = site.species.weight | ||
center += site.coords * wt | ||
total_weight += wt | ||
return center/ total_weight | ||
|
||
def get_a_cation_sites( | ||
struct: Structure, | ||
a_cation_center_species: str='C', | ||
radius_cutoff: float = 3.5, # in Angstroms | ||
) -> list: | ||
""" | ||
Get the indices of the A cation sites in the structure. | ||
Args: | ||
struct (Structure): structure | ||
a_cation_center_species (str, optional): Species of the A cation center. Defaults to 'C'. | ||
radius_cutoff (float, optional): Radius cutoff for finding the neighbours of the A cation center. \ | ||
Defaults to 3.5 Angstroms. | ||
""" | ||
# Get the central atom of all A cations, by default Carbon (e.g, A_cation = formamidinium) | ||
carbon_sites = [(index, site) for index, site in enumerate(struct) if site.species_string == a_cation_center_species] | ||
fa_molecules = [] | ||
count = 0 | ||
for index, carbon in carbon_sites: | ||
# Get the indices of all atoms bonded to the central atom | ||
neighbors = struct.get_neighbors(carbon, r= radius_cutoff) | ||
print([site.species_string for site in neighbors]) # Make sure we're getting the right atoms | ||
fa_molecules.append([index,]) | ||
fa_molecules[count] += ([site.index for site in neighbors]) | ||
count += 1 | ||
# assert all elements in list have the same length | ||
assert len(set([len(molecule) for molecule in fa_molecules])) == 1 | ||
return fa_molecules | ||
|
||
def rotate_a_cation( | ||
struct: Structure, | ||
fa_molecules: list, | ||
maximum_angle: int = 180, # in degrees | ||
rotation_axis: list=[0,1,0], | ||
): | ||
""" | ||
Rotates A cation molecules by random angles chosen between -maximum_angle and +maximum_angle. | ||
Args: | ||
struct (Structure): structure | ||
fa_molecules (list): list of lists with the indices of the sites for each molecule (e.g. [[0,1,2,3], [4,5,6,7]]) | ||
maximum_angle (int, optional): Random angles will be chosen between [-maximum_angle, +maximum_angle] Defaults to 180 degrees. | ||
rotation_axis (list, optional): Vector to rotate around. \ | ||
For formamidinium, the vector defined between the two Nitrogens (for FA). Defaults to [0,1,0]. | ||
Returns: | ||
Structure: structure with A cation molecules rotated | ||
""" | ||
struct_rotated = deepcopy(struct) | ||
# Need to perturb structure to break symmetries. \ | ||
# Otherwise, it breaks some of the FA molecules when rotating (does weird shit with the H bonded to the C) | ||
struct_rotated.perturb(distance = 0.000001) | ||
for sites in fa_molecules: | ||
angle = random.randrange(-maximum_angle, maximum_angle) | ||
#print(f"Rotating by {angle} degrees") | ||
center_of_mass = get_center_of_mass(struct_rotated, sites) | ||
struct_rotated.rotate_sites( | ||
indices = sites, | ||
theta = angle * np.pi / 180, | ||
axis = rotation_axis, | ||
anchor = center_of_mass, # struct_rotated[sites[0]].coords, | ||
to_unit_cell = False, | ||
) | ||
return struct_rotated |