"""
.. module:: Charge_displacement
:synopsis: Generate the charge_displacement interaction matrix.
.. moduleauthor:: D. Wang <dwang5@zoho.com>
"""
import numpy as np
from netCDF4 import Dataset
import time
from math import atan, sqrt, log
from supercell import Supercell
from ewald_dd import dd_set_parameters, dd_sum_over_k
[docs]class Charge_displacement(Supercell):
"""
The parameters are similar to that of 'charge-charge'.
.. note::
Reuse "ewald_dd.cpp" because of the similarity.
"""
def __init__(self, n1, n2, nz, lattice):
Supercell.__init__(self, n1, n2, nz, lattice)
self.dpij = np.zeros((self.nsites, 6))
self.dipole_matrix_calculated = False
def write_dipole_matrix(self, fn):
if self.dipole_matrix_calculated == False:
print("Calculate the matrix first ...")
self.generate_dipole_matrix()
self.dipole_matrix_calculated = True
dipm = Dataset(fn, "w", format="NETCDF4")
direction = dipm.createDimension("direction", 6)
ia = dipm.createDimension("ia", None)
directions = dipm.createVariable("direction", np.int32, ("direction"))
ias = dipm.createVariable("ia", np.int32, ("ia"))
# The actual 2-d varable.
matrix = dipm.createVariable('matrix', np.float64, ('ia', 'direction'))
dipm.description = 'Dipole matrix: interaction matrix'
dipm.history = 'Created at ' + time.ctime(time.time())
matrix[:, :] = self.dpij
dipm.close()
def generate_dipole_matrix(self):
pi = 4.0 * atan(1.0)
pi2 = pi * 2.0
tol = 1.0e-12
eta = sqrt(-log(tol))
gcut = 2.0 * eta ** 2
gcut2 = gcut ** 2
eta4 = 1.0 / (4 * eta ** 2)
am = np.zeros((3))
for i in range(3):
for k in range(3):
am[i] += self.a[k, i] ** 2
am[i] = sqrt(am[i])
mg1 = int(gcut * am[0] / pi2) + 1
mg2 = int(gcut * am[1] / pi2) + 1
mg3 = int(gcut * am[2] / pi2) + 1
print('Gcut: ', gcut, ' mg1, mg2, mg3: ', mg1, mg2, mg3)
# Set parameters to be used in the PYBIND11 C++ computation.
dd_set_parameters(self.b, mg1, mg2, mg3, gcut2, eta4)
pos0 = np.zeros(3)
pos0 = self.ixa[0] * self.lattice[0, :] \
+ self.iya[0] * self.lattice[1, :] \
+ self.iza[0] * self.lattice[2, :]
print(pos0)
for ia in range(self.nsites):
print('site: ', ia)
pos = np.zeros(3)
pos = self.ixa[ia] * self.lattice[0, :] \
+ self.iya[ia] * self.lattice[1, :] \
+ self.iza[ia] * self.lattice[2, :]
rx = pos[0]
ry = pos[1]
rz = pos[2]
c = 2.0 * pi / self.celvol
dum = np.zeros(6)
# print('Summing over k space')
dd_sum_over_k(dum, rx - pos0[0], ry - pos0[1], rz - pos0[2])
# The 2.0 comes from how the sum on k was done.
self.dpij[ia, :] = dum[:] * c * 2.0
self.dipole_matrix_calculated = True