10
$\begingroup$

In this paper, they have rotated the unit cell using a rotation matrix, so the axes are aligned with the atomic bonds. I would like to know how they calculated that rotation matrix, and which software to use to apply that rotation on a unit cell.

$\endgroup$
5
  • 2
    $\begingroup$ From the article "For this we first find the proper rotation matrix using the VESTA program [43]. Then we cal- culated the corresponding rotation angles and rotated the CrI3 unit cell using Atomsk" $\endgroup$ Commented Nov 20, 2021 at 13:52
  • $\begingroup$ @Tyberius but how to do that? $\endgroup$ Commented Nov 20, 2021 at 14:14
  • 1
    $\begingroup$ From not having used Vesta and just checking the manual, it doesn't seem like there is an automated feature to find a particular rotation matrix. What it could help with is determining the vector of a bond, which could then be used to calculate the rotation matrix as described on Math SE. Vesta can then be used to apply this rotation to your unit cell. $\endgroup$ Commented Nov 20, 2021 at 15:31
  • 2
    $\begingroup$ If using the approach @Tyberius mentions, Mathematica's RotationMatrix[{u,v}] command can make obtaining the rotation matrix very easy. $\endgroup$ Commented Nov 20, 2021 at 17:34
  • $\begingroup$ @Tyberius I still couldn't understand the approach? $\endgroup$ Commented Nov 21, 2021 at 16:35

2 Answers 2

4
$\begingroup$

Collecting my comments and clarifying them, in the paper they mention that they used VESTA and Atomsk to do this:

For this we first find the proper rotation matrix using the VESTA program [43]. Then we calculated the corresponding rotation angles and rotated the CrI3 unit cell using Atomsk

I don't know much about either of these programs, but I can at least point you to the mathematical procedure for rotating a vector onto another vector. Using Vesta, you should be able to determine the vector for a bond $\ce{A-B}$ (call the vector $\vec{u}$) from the coordinates of $\ce{A}$ and $\ce{B}$. You could then align this bond with $\vec{x}=(1,0,0)$ (for example), using the rotation matrix:

$$R=I+[U]_\times+[U]_\times^2\frac{1-\cos(\theta)}{\sin(\theta)^2}$$

with $\theta$ the angle between the $\vec{u}$ and $\vec{x}$ and $$[U]_\times=[\vec{u}\times \vec{x}]= \begin{bmatrix} 0 & -u_3 & u_2\\ u_3 & 0 & -u_1\\ u_2 & u_1 & 0\\ \end{bmatrix}$$

Once you have this rotation matrix, you can enter the Transform tab in VESTA which should allow you enter and apply this rotation matrix. As Anyon mentioned, some languages like Mathematica have built in functions to form this rotation matrix. VESTA itself may have such a function, but I haven't found one thus far.

$\endgroup$
4
  • $\begingroup$ That means if I have to rotate two bonds, then I need two different rotational matrix right? $\endgroup$ Commented May 27, 2024 at 19:58
  • $\begingroup$ @Kratos1611 potentially. Technically if there are two rotation matrices to achieve the configuration you want, you can multiply them together to get a single rotation matrix. It's also possible the configuration you want to achieve isn't possible (e.g. for a linear A-B-C, you wouldn't be able to simultaneously align A-B along the y-axis and B-C along the x-axis). $\endgroup$ Commented May 28, 2024 at 0:33
  • $\begingroup$ Ok, I understand. Kindly look at this question of mine mattermodeling.stackexchange.com/questions/13038/… . Here in P2 like structure total 18 O-TM-O bond which I want to align along z axis. Is it allowed to align all bond together? or Should I rotate a particular O-TM-O (choosing a TM atom) bond at an one time ? $\endgroup$ Commented May 28, 2024 at 5:26
  • $\begingroup$ can you comment on this issue mentioned above? @Tyberius $\endgroup$ Commented May 29, 2024 at 7:23
0
$\begingroup$

I have written a code in python for to handle P2 like structure (I need to align 18 O-TM-O bond) to align O-TM-O bond along z axis, still I am not sure how much accurate this code, The code is,

import numpy as np def read_poscar(POSCAR): with open(POSCAR, 'r') as f: lines = f.readlines() system_name = lines[0].strip() scale_factor = float(lines[1].strip()) lattice_vectors = np.array([list(map(float, line.split())) for line in lines[2:5]]) element_symbols = lines[5].split() element_counts = list(map(int, lines[6].split())) total_atoms = sum(element_counts) coordinates_type = lines[7].strip() atomic_coordinates = np.array([list(map(float, line.split()[:3])) for line in lines[8:8+total_atoms]]) return system_name, scale_factor, lattice_vectors, element_symbols, element_counts, coordinates_type, atomic_coordinates def write_poscar(filename, system_name, scale_factor, lattice_vectors, element_symbols, element_counts, coordinates_type, atomic_coordinates): with open(filename, 'w') as f: f.write(system_name + '\n') f.write(f' {scale_factor:.16f}\n') for vec in lattice_vectors: f.write(' ' + ' '.join(f'{v:.16f}' for v in vec) + '\n') f.write(' ' + ' '.join(element_symbols) + '\n') f.write(' ' + ' '.join(map(str, element_counts)) + '\n') f.write(coordinates_type + '\n') for coord in atomic_coordinates: f.write(' ' + ' '.join(f'{c:.16f}' for c in coord) + '\n') def rotation_matrix_from_vectors(vec1, vec2): a, b = (vec1 / np.linalg.norm(vec1)).reshape(3), (vec2 / np.linalg.norm(vec2)).reshape(3) v = np.cross(a, b) c = np.dot(a, b) s = np.linalg.norm(v) I = np.identity(3) v_cross = np.array([[0, -v[2], v[1]], [v[2], 0, -v[0]], [-v[1], v[0], 0]]) R = I + v_cross + np.matmul(v_cross, v_cross) * ((1 - c) / (s ** 2)) return R def rotate_structure(atomic_coordinates, lattice_vectors, target_vector, bonds): bond_vectors = [] for oxygen_index1, transition_metal_index, oxygen_index2 in bonds: bond_vector1 = atomic_coordinates[transition_metal_index] - atomic_coordinates[oxygen_index1] bond_vector2 = atomic_coordinates[transition_metal_index] - atomic_coordinates[oxygen_index2] bond_vector = (bond_vector1 + bond_vector2) / 2 # Average vector to represent the bond alignment bond_vector /= np.linalg.norm(bond_vector) bond_vectors.append(bond_vector) # Calculate the average bond vector average_bond_vector = np.mean(bond_vectors, axis=0) # Compute the rotation matrix to align the average bond vector with the target vector R = rotation_matrix_from_vectors(average_bond_vector, target_vector) print(R) # Apply the rotation new_atomic_coordinates = np.dot(atomic_coordinates, R.T) new_lattice_vectors = np.dot(lattice_vectors, R.T) return new_atomic_coordinates, new_lattice_vectors def main(): poscar_file = 'filepath/POSCAR' new_poscar_file = 'filepath/POSCAR_rotated' target_vector = np.array([0, 0, 1]) # Target vector along the z-axis system_name, scale_factor, lattice_vectors, element_symbols, element_counts, coordinates_type, atomic_coordinates = read_poscar(poscar_file) # Define the bonds as tuples of (oxygen_index1, transition_metal_index, oxygen_index2) bonds = [ (50, 6, 45), # Example bond, modify with real indices (54, 14, 60), (65, 16, 64), (38, 0, 33), (46, 10, 53), (34, 4, 41), (30, 2, 37), (61, 12, 57), (42, 8, 49), (51, 7, 59), (55, 15, 40), (35, 5, 44), (39, 1, 48), (58, 17, 32), (43, 9, 63), (62, 13, 36), (47, 11, 56), (31, 3, 52) ] new_atomic_coordinates, new_lattice_vectors = rotate_structure( atomic_coordinates, lattice_vectors, target_vector, bonds ) write_poscar(new_poscar_file, system_name, scale_factor, new_lattice_vectors, element_symbols, element_counts, coordinates_type, new_atomic_coordinates) if __name__ == '__main__': main() 
$\endgroup$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.