by DonSoreno » Sun Aug 18, 2024 12:24 am
I wrote a python script that computes the eigenfunctions (-> ~orbitals) of a 4d lattice, but still without the boundary conditions that are needed to 100% correctly simulate orbitals.
And the lowest eigenvalue/energy is of course a spherical wavefunction.
Unfortunately I cannot upload a screenshot.
The order of the orbitals doesnt really change, the first is a spherical wavefunction, then p-orbitals, then d-orbitals.
Here's the python code:
import numpy
import scipy
import matplotlib.pyplot as plt
"""
generates 4d coordinates from 1d index in the space.
Most signifcant coordinate first.
"""
def idx_to_coord(idx):
return numpy.array([
idx//(linear_res**3)%linear_res,
(idx//(linear_res**2))%linear_res,
(idx//(linear_res))%linear_res,
idx%linear_res
])#use numpy array, so we can do arithmetic operations on it.
def coord_to_idx(coord:numpy.array):
return sum([coord[i]*linear_res**(3-i) for i in range(4)])
#create volume of 4d space, to compute eigenfunctions of laplacian of a hypothetical 4d electron around nuclues.
def fold_vector(vector):
res = numpy.zeros([linear_res]*4)
for i in range(vector.shape[0]):
coord = idx_to_coord(i)
res[coord[0],coord[1],coord[2],coord[3]] = vector[i]
return res
linear_res = 11
adjacency_matrix = numpy.zeros([linear_res**4,linear_res**4])
offsets = [numpy.array([x,y,z,w]) for x in range(-1,2) for y in range(-1,2) for z in range(-1,2) for w in range(-1,2)]
offsets = [offset for offset in offsets if numpy.linalg.norm(offset)>0]
for i in range(linear_res**4):# about 1000 iterations.
#the node i has 24 neighbors.
coord = idx_to_coord(i)
#generate tesseract of neighbors offsets.
for offset in offsets:
#check if new coordinates in bounds
if numpy.any(coord+offset<0) or numpy.any(coord+offset>=linear_res):
continue
new_coord = coord+offset
j = coord_to_idx(new_coord)
adjacency_matrix[i,j] = 1/numpy.linalg.norm(offset)
#connect diagonal elements with weight 1/1.414
print("filled the matrix.")
degree_matrix = numpy.diag(numpy.sum(adjacency_matrix,axis=1))
print(degree_matrix)
laplacian = degree_matrix - adjacency_matrix
"""
for idx in range(linear_res**4):
coord = idx_to_coord(idx)
#check if vertex lies on the outside boundary.
if numpy.any(coord==0) or numpy.any(coord==linear_res-1):
#if vertex on boundary, we want all eigenvectors to be zero at this vertex.
laplacian[idx,:] = 0
"""
#boundary conditions are buggy, so comment them out for now.
laplacian_sparse = scipy.sparse.csr_matrix(laplacian, dtype=numpy.float64)
#compute eigenvalues and eigenvectors of the laplacian.
#For atomic orbitals, we are interested in the lowest energy orbitals.
print("compute eigenvectors.")
num_eigenvectors = 20 #how many eigenvectors to compute.
eigenvalues,eigenvectors = scipy.sparse.linalg.eigs(laplacian_sparse,k=num_eigenvectors,which='SM')
#compute the lowest eigenvalues/eigenvectors, for lowest energy orbitals.
#print 2d projection of first eigenvector as heat map.
#
plt.figure()
center = numpy.array([linear_res//2,linear_res//2,linear_res//2,linear_res//2])
potential_kernel = numpy.array([
[
[
[min(1,1/numpy.linalg.norm(numpy.array([x,y,z,w])-center)) for x in range(linear_res)]
for y in range(linear_res)] for z in range(linear_res)]
for w in range(linear_res)
])
for i in range(10):
volume = numpy.multiply(potential_kernel,fold_vector(eigenvectors[:,i]))
#apply 1/r^2 potential from the center of the volume.
fig, axis = plt.subplots(linear_res,linear_res)
#show slices of the 4d volume.
for j in range(linear_res):
for l in range(linear_res):
axis[j,l].imshow(volume[j,l,:,:])
fig.show()
plt.show()