Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Some modification and new files for QHA #294

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 193 additions & 0 deletions abipy/dfpt/deformation_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# deformation_utils.py

import numpy as np
from pymatgen.core import Structure, Lattice, Element
from abipy.core.symmetries import AbinitSpaceGroup
from pymatgen.symmetry.analyzer import SpacegroupAnalyzer
from abipy.abio.inputs import AbinitInput
import re


def generate_deformations_volumic(structure, eps_V=0.02, scales=None):
if scales is None:
scales = [-1, 0, 1, 2, 3]
rprim = structure.lattice.matrix
structures_new = {}

for i in scales:
rprim2 = np.copy(rprim)
rprim2[:, :] = rprim[:, :] * (1.00 + eps_V * i)**(1/3.)

structure2 = structure.copy()
structure2.lattice = Lattice(rprim2)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want I think you can simplify the code by using internal pyamtgen functions.

structure2 = structure.copy()
structure2.scale_lattice(scopy.volume*(1.00 + eps_V * i))

should lead to the same result.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This new command does not work.

#structure2.scale_lattice(structure2.volume*(1.00 + eps_V * i))
namei = int(round(1000 * (1.00 + eps_V * i)))
formatted_namei = f"{namei:04d}"
structures_new[formatted_namei] = structure2


return structures_new

def generate_deformations(structure , eps=0.005):
spgrp = AbinitSpaceGroup.from_structure(structure )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a question about this point: is it relevant that the spacegroup obtained here is guaranteed to match 100% the one in abinit? In that case it would be better to use AbinitInput.abiget_spacegroup, since AbinitSpaceGroup.from_structure relies on the SpacegroupAnalyzer`. If instead it is just important that the result is consistent throught the code, this should be fine.

In case, this may apply to all the cases where AbinitSpacegroup.from_structure is used

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I attempt to use AbinitInput.abiget_spacegroup, but I have not succeed . could you please change it as your prefer ?

print (spgrp)
spgrp_number=spgrp.spgid
rprim= structure.lattice.matrix

rprim2 = np.copy(rprim)
rprim_new = {}
structures_new = {}

if 1 <= spgrp_number <= 2:
disp=[[1,1,1,1,1,1], [0,1,1,1,1,1], [2,1,1,1,1,1], [1,0,1,1,1,1], [1,2,1,1,1,1], [1,1,0,1,1,1],
[1,1,2,1,1,1], [1,1,1,0,1,1], [1,1,1,2,1,1], [1,1,1,1,0,1], [1,1,1,1,2,1], [1,1,1,1,1,0],
[1,1,1,1,1,2], [0,0,1,1,1,1], [1,0,0,1,1,1], [1,1,0,0,1,1], [1,1,1,0,0,1], [1,1,1,1,0,0],
[0,1,0,1,1,1], [0,1,1,0,1,1], [0,1,1,1,0,1], [0,1,1,1,1,0], [1,0,1,0,1,1], [1,0,1,1,0,1],
[1,0,1,1,1,0], [1,1,0,1,0,1], [1,1,0,1,1,0], [1,1,1,0,1,0] , [0 ,0,0,0,0,0]]
if abs(rprim[1, 0]) > 1e-9 or abs(rprim[2, 0]) > 1e-9 or abs(rprim[2, 1]) > 1e-9:
print("Warning: The lattice is oriented such that xz =xy =yz =0 .")
rprim0 = np.copy(rprim)
a=rprim[0, :]
b=rprim[1, :]
c=rprim[2, :]
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
norm_c = np.linalg.norm(c)

# Compute angles between vectors
cos_ab = np.dot(a, b) / (norm_a * norm_b)
cos_ac = np.dot(a, c) / (norm_a * norm_c)
cos_bc = np.dot(b, c) / (norm_b * norm_c)

rprim0[0,0] = 1.0
rprim0[0,1] = 0.0
rprim0[0,2] = 0.0
rprim0[1,0] = cos_ab
rprim0[1,1] = np.sqrt(1-cos_ab**2)
rprim0[1,2] = 0.0
rprim0[2,0] = cos_ac
rprim0[2,1] = (cos_bc-rprim0[1,0]*rprim0[2,0])/rprim0[1,1]
rprim0[2,2] = np.sqrt(1.0-rprim0[2,0]**2-rprim0[2,1]**2)
rprim0[0,:] = rprim0[0,:]*norm_a
rprim0[1,:] = rprim0[1,:]*norm_b
rprim0[2,:] = rprim0[2,:]*norm_c
print("Old rprim:")
print(rprim)
print("New rprim:")
print(rprim0)

for pair in disp:
i,j,k,l,m,n = pair
rprim2[ :,0] = rprim0[ :,0] * (1.00 + eps * i) + rprim0[ :,1] * (eps * l) +rprim0[ :,2] * (eps * m)
rprim2[ :,1] = rprim0[ :,1] * (1.00 + eps * j) + rprim0[ :,2] * (eps * n)
rprim2[ :,2] = rprim0[ :,2] * (1.00 + eps * k)

namei = int(round(1000 * (1.00 + eps * i)))
namej = int(round(1000 * (1.00 + eps * j)))
namek = int(round(1000 * (1.00 + eps * k)))
namel = int(round(1000 * (1.00 + eps * l)))
namem = int(round(1000 * (1.00 + eps * m)))
namen = int(round(1000 * (1.00 + eps * n)))
formatted_namei = f"{namei:04d}_{namej:04d}_{namek:04d}_{namel:04d}_{namem:04d}_{namen:04d}"

structure2=structure.copy()
structure2.lattice=Lattice(rprim2)
structures_new[formatted_namei] = structure2

return structures_new
elif 3 <= spgrp_number <= 15:
disp=[[1,1,1,1], [0,1,1,1], [2,1,1,1], [1,0,1,1], [1,2,1,1], [1,1,0,1], [1,1,2,1], [1,1,1,0],
[1,1,1,2], [0,0,1,1], [1,0,0,1], [1,1,0,0], [0,1,0,1], [1,0,1,0], [0,1,1,0]]
if abs(rprim[1, 0]) > 1e-9 or abs(rprim[0, 1]) > 1e-9 or abs(rprim[2, 1]) > 1e-9 or abs(rprim[1, 2]) > 1e-9:
print("Error: Monoclinic structure with yx=xy=0 and yz=zy=0 lattice required.")
elif abs(rprim[0, 2]) > 1e-9 :
print("Warning: The lattice is oriented such that xz = 0.")
rprim0 = np.copy(rprim)
a=rprim[0, :]
b=rprim[1, :]
c=rprim[2, :]
norm_a = np.linalg.norm(a)
norm_b = np.linalg.norm(b)
norm_c = np.linalg.norm(c)

# Compute angles between vectors
cos_ab = np.dot(a, b) / (norm_a * norm_b)
cos_ac = np.dot(a, c) / (norm_a * norm_c)
cos_bc = np.dot(b, c) / (norm_b * norm_c)

rprim0[0,0] = norm_a
rprim0[0,2] = 0.0
rprim0[1,1] = norm_b
rprim0[2,0] = norm_c*cos_ac
rprim0[2,2] = norm_c*np.sqrt(1-cos_ac**2)
print("Old rprim:")
print(rprim)
print("New rprim:")
print(rprim0)

for pair in disp:
i,j,k,l = pair
rprim2[ :,0] = rprim0[ :,0] * (1.00 + eps * i) +rprim0[ :,2] * (eps * l)
rprim2[ :,1] = rprim0[ :,1] * (1.00 + eps * j)
rprim2[ :,2] = rprim0[ :,2] * (1.00 + eps * k)

namei = int(round(1000 * (1.00 + eps * i)))
namej = int(round(1000 * (1.00 + eps * j)))
namek = int(round(1000 * (1.00 + eps * k)))
namel = int(round(1000 * (1.00 + eps * l)))
formatted_namei = f"{namei:04d}_{namej:04d}_{namek:04d}_{namel:04d}"

structure2=structure.copy()
structure2.lattice=Lattice(rprim2)
structures_new[formatted_namei] = structure2

return structures_new
elif 16 <= spgrp_number <= 74:
disp=[[0,0,1],[0,1,0],[1,0,0],[1,1,1],[0,1,1],[2,1,1],[1,0,1],[1,2,1],[1,1,0],[1,1,2]]
for pair in disp:
i,j,k = pair
rprim2[ :,0] = rprim[ :,0] * (1.00 + eps * i)
rprim2[ :,1] = rprim[ :,1] * (1.00 + eps * j)
rprim2[ :,2] = rprim[ :,2] * (1.00 + eps * k)

namei = int(round(1000 * (1.00 + eps * i)))
namej = int(round(1000 * (1.00 + eps * j)))
namek = int(round(1000 * (1.00 + eps * k)))
formatted_namei = f"{namei:04d}_{namej:04d}_{namek:04d}"

structure2=structure.copy()
structure2.lattice=Lattice(rprim2)
structures_new[formatted_namei] = structure2

return structures_new
elif 75 <= spgrp_number <= 194:
disp=[[0,0],[1,1],[0,1],[2,1],[1,0],[1,2]]
for pair in disp:
i, k = pair
rprim2[ :,0] = rprim[ :,0] * (1.00 + eps * i)
rprim2[ :,1] = rprim[ :,1] * (1.00 + eps * i)
rprim2[ :,2] = rprim[ :,2] * (1.00 + eps * k)

namei = int(round(1000 * (1.00 + eps * i)))
namek = int(round(1000 * (1.00 + eps * k)))
formatted_namei = f"{namei:04d}_{namek:04d}"
rprim_new[formatted_namei] = rprim2

structure2=structure.copy()
structure2.lattice=Lattice(rprim2)
structures_new[formatted_namei] = structure2

return structures_new
elif 195 <= spgrp_number <= 230:
for i in range(3):
rprim2[ :,0] = rprim[ :,0] * (1.00 + eps * i)
rprim2[ :,1] = rprim[ :,1] * (1.00 + eps * i)
rprim2[ :,2] = rprim[ :,2] * (1.00 + eps * i)
namei = int(round(1000 * (1.00 + eps * i)))
formatted_namei = f"{namei:04d}"

structure2=structure.copy()
structure2.lattice=Lattice(rprim2)
structures_new[formatted_namei] = structure2
return structures_new

Loading
Loading