Source code for charge_displacement

"""
.. 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