MolHandling Translation
In this commit were created a System class to manage the functions between two atoms and various new functions were translated Signed-off-by: Vitor Hideyoshi <vitor.h.n.batista@gmail.com>
This commit is contained in:
@@ -11,144 +11,144 @@ from DPpack.SetGlobals import *
|
||||
|
||||
####################################### functions ######################################
|
||||
|
||||
def center_of_mass(molecule):
|
||||
# def center_of_mass(molecule):
|
||||
|
||||
com = np.zeros(3)
|
||||
total_mass = 0.0
|
||||
for atom in molecule:
|
||||
total_mass += atom['mass']
|
||||
position = np.array([atom['rx'], atom['ry'], atom['rz']])
|
||||
com += atom['mass'] * position
|
||||
# com = np.zeros(3)
|
||||
# total_mass = 0.0
|
||||
# for atom in molecule:
|
||||
# total_mass += atom['mass']
|
||||
# position = np.array([atom['rx'], atom['ry'], atom['rz']])
|
||||
# com += atom['mass'] * position
|
||||
|
||||
com = com / total_mass
|
||||
# com = com / total_mass
|
||||
|
||||
return com
|
||||
# return com
|
||||
|
||||
|
||||
|
||||
def center_of_mass_distance(molecule1, molecule2):
|
||||
# def center_of_mass_distance(molecule1, molecule2):
|
||||
|
||||
com1 = center_of_mass(molecule1)
|
||||
com2 = center_of_mass(molecule2)
|
||||
dx = com1[0] - com2[0]
|
||||
dy = com1[1] - com2[1]
|
||||
dz = com1[2] - com2[2]
|
||||
distance = math.sqrt(dx**2 + dy**2 + dz**2)
|
||||
# com1 = center_of_mass(molecule1)
|
||||
# com2 = center_of_mass(molecule2)
|
||||
# dx = com1[0] - com2[0]
|
||||
# dy = com1[1] - com2[1]
|
||||
# dz = com1[2] - com2[2]
|
||||
# distance = math.sqrt(dx**2 + dy**2 + dz**2)
|
||||
|
||||
return distance
|
||||
# return distance
|
||||
|
||||
|
||||
|
||||
def center_of_mass_to_origin(molecule):
|
||||
# def center_of_mass_to_origin(molecule):
|
||||
|
||||
com = center_of_mass(molecule)
|
||||
for atom in molecule:
|
||||
atom['rx'] -= com[0]
|
||||
atom['ry'] -= com[1]
|
||||
atom['rz'] -= com[2]
|
||||
# com = center_of_mass(molecule)
|
||||
# for atom in molecule:
|
||||
# atom['rx'] -= com[0]
|
||||
# atom['ry'] -= com[1]
|
||||
# atom['rz'] -= com[2]
|
||||
|
||||
return
|
||||
# return
|
||||
|
||||
|
||||
|
||||
def charges_and_dipole(molecule):
|
||||
# def charges_and_dipole(molecule):
|
||||
|
||||
eA_to_Debye = 1/0.20819434
|
||||
charge = 0
|
||||
dipole = np.zeros(3)
|
||||
for atom in molecule:
|
||||
position = np.array([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
dipole += atom['chg'] * position
|
||||
charge += atom['chg']
|
||||
# eA_to_Debye = 1/0.20819434
|
||||
# charge = 0
|
||||
# dipole = np.zeros(3)
|
||||
# for atom in molecule:
|
||||
# position = np.array([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
# dipole += atom['chg'] * position
|
||||
# charge += atom['chg']
|
||||
|
||||
dipole *= eA_to_Debye
|
||||
total_dipole = math.sqrt(dipole[0]**2 + dipole[1]**2 + dipole[2]**2)
|
||||
# dipole *= eA_to_Debye
|
||||
# total_dipole = math.sqrt(dipole[0]**2 + dipole[1]**2 + dipole[2]**2)
|
||||
|
||||
return [charge, dipole[0], dipole[1], dipole[2], total_dipole]
|
||||
# return [charge, dipole[0], dipole[1], dipole[2], total_dipole]
|
||||
|
||||
|
||||
|
||||
def distances_between_atoms(molecule):
|
||||
# def distances_between_atoms(molecule):
|
||||
|
||||
distances = []
|
||||
dim = len(molecule)
|
||||
for atom1 in molecule:
|
||||
if atom1['na'] != ghost_number:
|
||||
for atom2 in molecule:
|
||||
if atom2['na'] != ghost_number:
|
||||
dx = atom1['rx'] - atom2['rx']
|
||||
dy = atom1['ry'] - atom2['ry']
|
||||
dz = atom1['rz'] - atom2['rz']
|
||||
distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
# distances = []
|
||||
# dim = len(molecule)
|
||||
# for atom1 in molecule:
|
||||
# if atom1['na'] != ghost_number:
|
||||
# for atom2 in molecule:
|
||||
# if atom2['na'] != ghost_number:
|
||||
# dx = atom1['rx'] - atom2['rx']
|
||||
# dy = atom1['ry'] - atom2['ry']
|
||||
# dz = atom1['rz'] - atom2['rz']
|
||||
# distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
|
||||
return np.array(distances).reshape(dim, dim)
|
||||
# return np.array(distances).reshape(dim, dim)
|
||||
|
||||
|
||||
|
||||
def eixos(molecule):
|
||||
# def eixos(molecule):
|
||||
|
||||
eixos = np.zeros(3)
|
||||
if len(molecule) == 2:
|
||||
position1 = np.array([ molecule[0]['rx'], molecule[0]['ry'], molecule[0]['rz'] ])
|
||||
position2 = np.array([ molecule[1]['rx'], molecule[1]['ry'], molecule[1]['rz'] ])
|
||||
eixos = position2 - position1
|
||||
eixos /= linalg.norm(eixos)
|
||||
elif len(molecule) > 2:
|
||||
position1 = np.array([ molecule[0]['rx'], molecule[0]['ry'], molecule[0]['rz'] ])
|
||||
position2 = np.array([ molecule[1]['rx'], molecule[1]['ry'], molecule[1]['rz'] ])
|
||||
position3 = np.array([ molecule[2]['rx'], molecule[2]['ry'], molecule[2]['rz'] ])
|
||||
v1 = position2 - position1
|
||||
v2 = position3 - position1
|
||||
v3 = np.cross(v1, v2)
|
||||
v2 = np.cross(v1, v3)
|
||||
v1 /= linalg.norm(v1)
|
||||
v2 /= linalg.norm(v2)
|
||||
v3 /= linalg.norm(v3)
|
||||
eixos = np.array([[v1[0], v1[1], v1[2]],
|
||||
[v2[0], v2[1], v2[2]],
|
||||
[v3[0], v3[1], v3[2]]])
|
||||
# eixos = np.zeros(3)
|
||||
# if len(molecule) == 2:
|
||||
# position1 = np.array([ molecule[0]['rx'], molecule[0]['ry'], molecule[0]['rz'] ])
|
||||
# position2 = np.array([ molecule[1]['rx'], molecule[1]['ry'], molecule[1]['rz'] ])
|
||||
# eixos = position2 - position1
|
||||
# eixos /= linalg.norm(eixos)
|
||||
# elif len(molecule) > 2:
|
||||
# position1 = np.array([ molecule[0]['rx'], molecule[0]['ry'], molecule[0]['rz'] ])
|
||||
# position2 = np.array([ molecule[1]['rx'], molecule[1]['ry'], molecule[1]['rz'] ])
|
||||
# position3 = np.array([ molecule[2]['rx'], molecule[2]['ry'], molecule[2]['rz'] ])
|
||||
# v1 = position2 - position1
|
||||
# v2 = position3 - position1
|
||||
# v3 = np.cross(v1, v2)
|
||||
# v2 = np.cross(v1, v3)
|
||||
# v1 /= linalg.norm(v1)
|
||||
# v2 /= linalg.norm(v2)
|
||||
# v3 /= linalg.norm(v3)
|
||||
# eixos = np.array([[v1[0], v1[1], v1[2]],
|
||||
# [v2[0], v2[1], v2[2]],
|
||||
# [v3[0], v3[1], v3[2]]])
|
||||
|
||||
return eixos
|
||||
# return eixos
|
||||
|
||||
|
||||
|
||||
def inertia_tensor(molecule):
|
||||
# def inertia_tensor(molecule):
|
||||
|
||||
com = center_of_mass(molecule)
|
||||
Ixx = Ixy = Ixz = Iyy = Iyz = Izz = 0.0
|
||||
for atom in molecule:
|
||||
#### Obtain the displacement from the center of mass
|
||||
dx = atom['rx'] - com[0]
|
||||
dy = atom['ry'] - com[1]
|
||||
dz = atom['rz'] - com[2]
|
||||
#### Update the diagonal components of the tensor
|
||||
Ixx += atom['mass'] * (dy**2 + dz**2)
|
||||
Iyy += atom['mass'] * (dz**2 + dx**2)
|
||||
Izz += atom['mass'] * (dx**2 + dy**2)
|
||||
#### Update the off-diagonal components of the tensor
|
||||
Ixy += atom['mass'] * dx * dy * -1
|
||||
Ixz += atom['mass'] * dx * dz * -1
|
||||
Iyz += atom['mass'] * dy * dz * -1
|
||||
# com = center_of_mass(molecule)
|
||||
# Ixx = Ixy = Ixz = Iyy = Iyz = Izz = 0.0
|
||||
# for atom in molecule:
|
||||
# #### Obtain the displacement from the center of mass
|
||||
# dx = atom['rx'] - com[0]
|
||||
# dy = atom['ry'] - com[1]
|
||||
# dz = atom['rz'] - com[2]
|
||||
# #### Update the diagonal components of the tensor
|
||||
# Ixx += atom['mass'] * (dy**2 + dz**2)
|
||||
# Iyy += atom['mass'] * (dz**2 + dx**2)
|
||||
# Izz += atom['mass'] * (dx**2 + dy**2)
|
||||
# #### Update the off-diagonal components of the tensor
|
||||
# Ixy += atom['mass'] * dx * dy * -1
|
||||
# Ixz += atom['mass'] * dx * dz * -1
|
||||
# Iyz += atom['mass'] * dy * dz * -1
|
||||
|
||||
return np.array([[Ixx, Ixy, Ixz],
|
||||
[Ixy, Iyy, Iyz],
|
||||
[Ixz, Iyz, Izz]])
|
||||
# return np.array([[Ixx, Ixy, Ixz],
|
||||
# [Ixy, Iyy, Iyz],
|
||||
# [Ixz, Iyz, Izz]])
|
||||
|
||||
|
||||
|
||||
def minimum_distance(molecule1, molecule2):
|
||||
# def minimum_distance(molecule1, molecule2):
|
||||
|
||||
distances = []
|
||||
for atom1 in molecule1:
|
||||
if atom1['na'] != ghost_number:
|
||||
for atom2 in molecule2:
|
||||
if atom2['na'] != ghost_number:
|
||||
dx = atom1['rx'] - atom2['rx']
|
||||
dy = atom1['ry'] - atom2['ry']
|
||||
dz = atom1['rz'] - atom2['rz']
|
||||
distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
# distances = []
|
||||
# for atom1 in molecule1:
|
||||
# if atom1['na'] != ghost_number:
|
||||
# for atom2 in molecule2:
|
||||
# if atom2['na'] != ghost_number:
|
||||
# dx = atom1['rx'] - atom2['rx']
|
||||
# dy = atom1['ry'] - atom2['ry']
|
||||
# dz = atom1['rz'] - atom2['rz']
|
||||
# distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
|
||||
return min(distances)
|
||||
# return min(distances)
|
||||
|
||||
|
||||
|
||||
@@ -224,15 +224,15 @@ def calculate_step(gradient, hessian, fh):
|
||||
|
||||
|
||||
|
||||
def read_position(molecule):
|
||||
# def read_position(molecule):
|
||||
|
||||
position_list = []
|
||||
for atom in molecule:
|
||||
position_list.extend([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
position = np.array(position_list)
|
||||
position *= ang2bohr
|
||||
# position_list = []
|
||||
# for atom in molecule:
|
||||
# position_list.extend([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
# position = np.array(position_list)
|
||||
# position *= ang2bohr
|
||||
|
||||
return position
|
||||
# return position
|
||||
|
||||
|
||||
|
||||
@@ -254,17 +254,17 @@ def update_molecule(position, fh):
|
||||
|
||||
|
||||
|
||||
def update_hessian(step, cur_gradient, old_gradient, hessian): ## According to the BFGS
|
||||
# def update_hessian(step, cur_gradient, old_gradient, hessian): ## According to the BFGS
|
||||
|
||||
dif_gradient = cur_gradient - old_gradient
|
||||
# dif_gradient = cur_gradient - old_gradient
|
||||
|
||||
mat1 = 1/np.dot(dif_gradient, step) * np.matmul(dif_gradient.T, dif_gradient)
|
||||
mat2 = 1/np.dot(step, np.matmul(hessian, step.T).T)
|
||||
mat2 *= np.matmul( np.matmul(hessian, step.T), np.matmul(step, hessian) )
|
||||
# mat1 = 1/np.dot(dif_gradient, step) * np.matmul(dif_gradient.T, dif_gradient)
|
||||
# mat2 = 1/np.dot(step, np.matmul(hessian, step.T).T)
|
||||
# mat2 *= np.matmul( np.matmul(hessian, step.T), np.matmul(step, hessian) )
|
||||
|
||||
hessian += mat1 - mat2
|
||||
# hessian += mat1 - mat2
|
||||
|
||||
return hessian
|
||||
# return hessian
|
||||
|
||||
|
||||
|
||||
@@ -406,14 +406,14 @@ def populate_asec_vdw(cycle, fh):
|
||||
|
||||
|
||||
|
||||
def principal_axes(inertia_tensor):
|
||||
# def principal_axes(inertia_tensor):
|
||||
|
||||
try:
|
||||
evals, evecs = linalg.eigh(inertia_tensor)
|
||||
except:
|
||||
sys.exit("Error: diagonalization of inertia tensor did not converge")
|
||||
# try:
|
||||
# evals, evecs = linalg.eigh(inertia_tensor)
|
||||
# except:
|
||||
# sys.exit("Error: diagonalization of inertia tensor did not converge")
|
||||
|
||||
return evals, evecs
|
||||
# return evals, evecs
|
||||
|
||||
|
||||
|
||||
@@ -463,73 +463,73 @@ def print_mol_info(molecule, fh):
|
||||
|
||||
|
||||
|
||||
def sizes_of_molecule(molecule):
|
||||
# def sizes_of_molecule(molecule):
|
||||
|
||||
x_list = []
|
||||
y_list = []
|
||||
z_list = []
|
||||
for atom in molecule:
|
||||
if atom['na'] != ghost_number:
|
||||
x_list.append(atom['rx'])
|
||||
y_list.append(atom['ry'])
|
||||
z_list.append(atom['rz'])
|
||||
# x_list = []
|
||||
# y_list = []
|
||||
# z_list = []
|
||||
# for atom in molecule:
|
||||
# if atom['na'] != ghost_number:
|
||||
# x_list.append(atom['rx'])
|
||||
# y_list.append(atom['ry'])
|
||||
# z_list.append(atom['rz'])
|
||||
|
||||
x_max = max(x_list)
|
||||
x_min = min(x_list)
|
||||
y_max = max(y_list)
|
||||
y_min = min(y_list)
|
||||
z_max = max(z_list)
|
||||
z_min = min(z_list)
|
||||
# x_max = max(x_list)
|
||||
# x_min = min(x_list)
|
||||
# y_max = max(y_list)
|
||||
# y_min = min(y_list)
|
||||
# z_max = max(z_list)
|
||||
# z_min = min(z_list)
|
||||
|
||||
sizes = [x_max - x_min, y_max - y_min, z_max - z_min]
|
||||
# sizes = [x_max - x_min, y_max - y_min, z_max - z_min]
|
||||
|
||||
return sizes
|
||||
# return sizes
|
||||
|
||||
|
||||
|
||||
def standard_orientation(molecule):
|
||||
# def standard_orientation(molecule):
|
||||
|
||||
center_of_mass_to_origin(molecule)
|
||||
tensor = inertia_tensor(molecule)
|
||||
evals, evecs = principal_axes(tensor)
|
||||
if round(linalg.det(evecs)) == -1:
|
||||
evecs[0,2] *= -1
|
||||
evecs[1,2] *= -1
|
||||
evecs[2,2] *= -1
|
||||
if round(linalg.det(evecs)) != 1:
|
||||
sys.exit("Error: could not make a rotation matrix while adopting the standard orientation")
|
||||
# center_of_mass_to_origin(molecule)
|
||||
# tensor = inertia_tensor(molecule)
|
||||
# evals, evecs = principal_axes(tensor)
|
||||
# if round(linalg.det(evecs)) == -1:
|
||||
# evecs[0,2] *= -1
|
||||
# evecs[1,2] *= -1
|
||||
# evecs[2,2] *= -1
|
||||
# if round(linalg.det(evecs)) != 1:
|
||||
# sys.exit("Error: could not make a rotation matrix while adopting the standard orientation")
|
||||
|
||||
rot_matrix = evecs.T
|
||||
for atom in molecule:
|
||||
position = np.array([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
new_position = np.matmul(rot_matrix, position.T).T
|
||||
atom['rx'] = new_position[0]
|
||||
atom['ry'] = new_position[1]
|
||||
atom['rz'] = new_position[2]
|
||||
# rot_matrix = evecs.T
|
||||
# for atom in molecule:
|
||||
# position = np.array([ atom['rx'], atom['ry'], atom['rz'] ])
|
||||
# new_position = np.matmul(rot_matrix, position.T).T
|
||||
# atom['rx'] = new_position[0]
|
||||
# atom['ry'] = new_position[1]
|
||||
# atom['rz'] = new_position[2]
|
||||
|
||||
return
|
||||
# return
|
||||
|
||||
|
||||
|
||||
def total_mass(molecule):
|
||||
# def total_mass(molecule):
|
||||
|
||||
mass = 0
|
||||
for atom in molecule:
|
||||
mass += atom['mass']
|
||||
# mass = 0
|
||||
# for atom in molecule:
|
||||
# mass += atom['mass']
|
||||
|
||||
return mass
|
||||
# return mass
|
||||
|
||||
|
||||
|
||||
def translate(molecule, vector):
|
||||
# def translate(molecule, vector):
|
||||
|
||||
new_molecule = deepcopy(molecule)
|
||||
for atom in new_molecule:
|
||||
atom['rx'] += vector[0]
|
||||
atom['ry'] += vector[1]
|
||||
atom['rz'] += vector[2]
|
||||
# new_molecule = deepcopy(molecule)
|
||||
# for atom in new_molecule:
|
||||
# atom['rx'] += vector[0]
|
||||
# atom['ry'] += vector[1]
|
||||
# atom['rz'] += vector[2]
|
||||
|
||||
return new_molecule
|
||||
# return new_molecule
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,31 +1,83 @@
|
||||
from DPpack.MolHandling import total_mass
|
||||
import os, sys
|
||||
import math
|
||||
import shutil
|
||||
import textwrap
|
||||
import numpy as np
|
||||
import sys, math
|
||||
from copy import deepcopy
|
||||
|
||||
import numpy as np
|
||||
from numpy import linalg
|
||||
|
||||
from DPpack.PTable import *
|
||||
from DPpack.Misc import *
|
||||
from DPpack.PTable import *
|
||||
from DPpack.SetGlobals import *
|
||||
|
||||
# Usaremos uma nova classe que ira conter toda interação entre moleculas
|
||||
|
||||
class System:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.molecule = []
|
||||
|
||||
def add_molecule(self, m):
|
||||
|
||||
self.molecule.append(m)
|
||||
|
||||
# Função que calcula a distância entre dois centros de massa
|
||||
# e por se tratar de uma função de dois atomos não deve ser
|
||||
# inserida dentro de Molecule
|
||||
def center_of_mass_distance(self, a, b):
|
||||
|
||||
com1 = self.molecule[a].center_of_mass()
|
||||
com2 = self.molecule[b].center_of_mass()
|
||||
dx = com1[0] - com2[0]
|
||||
dy = com1[1] - com2[1]
|
||||
dz = com1[2] - com2[2]
|
||||
distance = math.sqrt(dx**2 + dy**2 + dz**2)
|
||||
|
||||
return distance
|
||||
|
||||
def minimum_distance(self, index1, index2):
|
||||
|
||||
distances = []
|
||||
for atom1 in self.molecule[index1]:
|
||||
if atom1.na != ghost_number:
|
||||
for atom2 in self.molecule[index2]:
|
||||
if atom2.na != ghost_number:
|
||||
dx = atom1.rx - atom2.rx
|
||||
dy = atom1.ry - atom2.ry
|
||||
dz = atom1.rz - atom2.rz
|
||||
distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
|
||||
return min(distances)
|
||||
|
||||
# Classe que conterá toda informação e funções relacionadas a uma unica molecula
|
||||
|
||||
class Molecule:
|
||||
|
||||
def __init__(self):
|
||||
|
||||
self.atoms = [] # Lista de instancias de Atom
|
||||
self.positions = None # Array Numpy
|
||||
self.atom = [] # Lista de instancias de Atom
|
||||
self.position = None # Array Numpy
|
||||
self.energy = None # Array Numpy
|
||||
self.gradient = None # Array Numpy
|
||||
self.hessian = None # Array Numpy
|
||||
self.total_mass = 0
|
||||
|
||||
def add_atom(self, a):
|
||||
|
||||
self.atoms.append(a) # Inserção de um novo atomo
|
||||
self.atom.append(a) # Inserção de um novo atomo
|
||||
self.total_mass += a.mass
|
||||
|
||||
def center_of_mass(self):
|
||||
|
||||
com = np.zeros(3)
|
||||
total_mass = 0.0
|
||||
for atom in self.atoms:
|
||||
|
||||
for atom in self.atom:
|
||||
|
||||
total_mass += atom.mass
|
||||
com += atom.mass * np.array([atom.rx, atom.ry, atom.rz])
|
||||
|
||||
@@ -33,6 +85,182 @@ class Molecule:
|
||||
|
||||
return com
|
||||
|
||||
def center_of_mass_to_origin(self):
|
||||
|
||||
com = self.center_of_mass()
|
||||
|
||||
for atom in self.atom:
|
||||
|
||||
atom.rx -= com[0]
|
||||
atom.ry -= com[1]
|
||||
atom.rz -= com[2]
|
||||
|
||||
def charges_and_dipole(self):
|
||||
|
||||
eA_to_Debye = 1/0.20819434
|
||||
charge = 0
|
||||
dipole = np.zeros(3)
|
||||
for atom in self.atom:
|
||||
position = np.array([ atom.rx, atom.ry, atom.rz ])
|
||||
dipole += atom.chg * position
|
||||
charge += atom.chg
|
||||
|
||||
dipole *= eA_to_Debye
|
||||
total_dipole = math.sqrt(dipole[0]**2 + dipole[1]**2 + dipole[2]**2)
|
||||
|
||||
return [charge, dipole[0], dipole[1], dipole[2], total_dipole]
|
||||
|
||||
def distances_between_atoms(self):
|
||||
|
||||
distances = []
|
||||
dim = len(self.atom)
|
||||
for atom1 in self.atom:
|
||||
if atom1.na != ghost_number:
|
||||
for atom2 in self.atom:
|
||||
if atom2.na != ghost_number:
|
||||
dx = atom1.rx - atom2.rx
|
||||
dy = atom1.ry - atom2.ry
|
||||
dz = atom1.rz - atom2.rz
|
||||
distances.append(math.sqrt(dx**2 + dy**2 + dz**2))
|
||||
|
||||
return np.array(distances).reshape(dim, dim)
|
||||
|
||||
def eixos(self):
|
||||
|
||||
eixos = np.zeros(3)
|
||||
if len(self.atom) == 2:
|
||||
|
||||
position1 = np.array([ self.atom[0].rx, self.atom[0].ry, self.atom[0].rz ])
|
||||
position2 = np.array([ self.atom[1].rx, self.atom[1].ry, self.atom[1].rz ])
|
||||
eixos = position2 - position1
|
||||
eixos /= linalg.norm(eixos)
|
||||
|
||||
elif len(self.atom) > 2:
|
||||
|
||||
position1 = np.array([ self.atom[0].rx, self.atom[0].ry, self.atom[0].rz ])
|
||||
position2 = np.array([ self.atom[1].rx, self.atom[1].ry, self.atom[1].rz ])
|
||||
position3 = np.array([ self.atom[2].rx, self.atom[2].ry, self.atom[2].rz ])
|
||||
v1 = position2 - position1
|
||||
v2 = position3 - position1
|
||||
v3 = np.cross(v1, v2)
|
||||
v2 = np.cross(v1, v3)
|
||||
v1 /= linalg.norm(v1)
|
||||
v2 /= linalg.norm(v2)
|
||||
v3 /= linalg.norm(v3)
|
||||
eixos = np.array([[v1[0], v1[1], v1[2]],
|
||||
[v2[0], v2[1], v2[2]],
|
||||
[v3[0], v3[1], v3[2]]])
|
||||
|
||||
return eixos
|
||||
|
||||
def inertia_tensor(self):
|
||||
|
||||
com = self.center_of_mass()
|
||||
Ixx = Ixy = Ixz = Iyy = Iyz = Izz = 0.0
|
||||
|
||||
for atom in self.atom:
|
||||
|
||||
#### Obtain the displacement from the center of mass
|
||||
dx = atom.rx - com[0]
|
||||
dy = atom.ry - com[1]
|
||||
dz = atom.rz - com[2]
|
||||
#### Update the diagonal components of the tensor
|
||||
Ixx += atom.mass * (dy**2 + dz**2)
|
||||
Iyy += atom.mass * (dz**2 + dx**2)
|
||||
Izz += atom.mass * (dx**2 + dy**2)
|
||||
#### Update the off-diagonal components of the tensor
|
||||
Ixy += atom.mass * dx * dy * -1
|
||||
Ixz += atom.mass * dx * dz * -1
|
||||
Iyz += atom.mass * dy * dz * -1
|
||||
|
||||
return np.array([ [Ixx, Ixy, Ixz],
|
||||
[Ixy, Iyy, Iyz],
|
||||
[Ixz, Iyz, Izz] ])
|
||||
|
||||
def principal_axes(self):
|
||||
|
||||
try:
|
||||
evals, evecs = linalg.eigh(self.inertia_tensor())
|
||||
except:
|
||||
sys.exit("Error: diagonalization of inertia tensor did not converge")
|
||||
|
||||
return evals, evecs
|
||||
|
||||
def read_position(self):
|
||||
|
||||
position_list = []
|
||||
for atom in self.atom:
|
||||
position_list.extend([ atom.rx, atom.ry, atom.rz ])
|
||||
position = np.array(position_list)
|
||||
position *= ang2bohr
|
||||
|
||||
return position
|
||||
|
||||
def update_hessian(self, step, cur_gradient): ## According to the BFGS
|
||||
|
||||
dif_gradient = cur_gradient - self.gradient
|
||||
|
||||
mat1 = 1/np.dot(dif_gradient, step) * np.matmul(dif_gradient.T, dif_gradient)
|
||||
mat2 = 1/np.dot(step, np.matmul(self.hessian, step.T).T)
|
||||
mat2 *= np.matmul( np.matmul(self.hessian, step.T), np.matmul(step, hessian) )
|
||||
|
||||
self.hessian += mat1 - mat2
|
||||
|
||||
def sizes_of_molecule(self):
|
||||
|
||||
x_list = []
|
||||
y_list = []
|
||||
z_list = []
|
||||
|
||||
for atom in self.atom:
|
||||
if atom.na != ghost_number:
|
||||
x_list.append(atom.rx)
|
||||
y_list.append(atom.ry)
|
||||
z_list.append(atom.rz)
|
||||
|
||||
x_max = max(x_list)
|
||||
x_min = min(x_list)
|
||||
y_max = max(y_list)
|
||||
y_min = min(y_list)
|
||||
z_max = max(z_list)
|
||||
z_min = min(z_list)
|
||||
|
||||
sizes = [x_max - x_min, y_max - y_min, z_max - z_min]
|
||||
|
||||
return sizes
|
||||
|
||||
def standard_orientation(self):
|
||||
|
||||
self.center_of_mass_to_origin()
|
||||
tensor = self.inertia_tensor()
|
||||
evals, evecs = self.principal_axes()
|
||||
|
||||
if round(linalg.det(evecs)) == -1:
|
||||
evecs[0,2] *= -1
|
||||
evecs[1,2] *= -1
|
||||
evecs[2,2] *= -1
|
||||
if round(linalg.det(evecs)) != 1:
|
||||
sys.exit("Error: could not make a rotation matrix while adopting the standard orientation")
|
||||
|
||||
rot_matrix = evecs.T
|
||||
for atom in self.atom:
|
||||
position = np.array([ atom.rx, atom.ry, atom.rz ])
|
||||
new_position = np.matmul(rot_matrix, position.T).T
|
||||
atom.rx = new_position[0]
|
||||
atom.ry = new_position[1]
|
||||
atom.rz = new_position[2]
|
||||
|
||||
def translate(self, vector):
|
||||
|
||||
new_molecule = deepcopy(self)
|
||||
|
||||
for atom in new_molecule.atom:
|
||||
|
||||
atom.rx += vector[0]
|
||||
atom.ry += vector[1]
|
||||
atom.rz += vector[2]
|
||||
|
||||
return new_molecule
|
||||
|
||||
class Atom:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user