Python | Material Science | Graphene Energy Simulation Issue: Unexpected ‘K’ Constant Factorization in Atomistic Structure Calculation

????

I’m currently working on an energy calculation for an atomistic structure (Graphene) and would appreciate some help in verifying my calculations. Specifically, I want to ensure that certain constants used in my code remain consistent throughout different computations.

To simplify my explanation:

I’ve defined a constant K = 63.9 which is integral to the energy calculation within the function calculate_energy(distances, bonds).

The distances between atoms are computed using several functions that plot the atoms and determine the distances between them. In the stable state, the energy should ideally be 0.

As part of testing my code, I’ve created a plot showing the relationship between energy growth and lattice constant growth (a). This plot helps me verify if I consistently get the same “K” constant (where the coefficient of “K” is the slope of the energy versus lattice constant plot) for each energy calculation, even when expanding the unit cell.

THE PROBLEM:
Despite my efforts, I’m encountering a multiplication factor of approximately 1.16667 on the K constant. Instead of the expected 63.9, I’m getting around 74.5520. I’ve thoroughly reviewed my script but cannot pinpoint the source of this factorization.

Additional Information:

The energy calculation involves calculating bond lengths and angles within the graphene lattice.
The unit cell is expanded by varying the lattice constant a and observing its effect on the total energy.
I’m particularly interested in understanding why there’s a deviation from the expected K constant and how to rectify it.
Any insights or suggestions on where I might look to resolve this issue would be greatly appreciated! Thank you in advance for your help.

SCRIPT SNIPPET:

import numpy as np
import matplotlib.pyplot as plt

# Constants
K = 63.9 # Force constant for bond elongation
xi = 1.56  # Unknown constant (not used in this code yet)
ideal_angle = 120  # Ideal bond angle in degrees
angle_constant = 1.0  # Constant for angle deviation energy contribution

# Define additional basis vectors
origin = np.array([0, 0])

# Function to plot lattice vectors
def plot_vectors(vectors, origin, color):
    for vector in vectors:
        plt.quiver(*origin, *vector, color=color, angles='xy', scale_units='xy', scale=1, width=0.003)

# Function to plot rectangle unit cell
def plot_rectangle(origin, V1, d2, color):
    rect_vertices = [
        origin,
        origin + V1,
        origin + 3 * d2,
        origin + V1 + 3 * d2
    ]
    rect_vertices = np.array(rect_vertices)
    rect_indices = [0, 2, 3, 1, 0]
    for i in range(len(rect_indices) - 1):
        plt.plot([rect_vertices[rect_indices[i]][0], rect_vertices[rect_indices[i + 1]][0]],
                 [rect_vertices[rect_indices[i]][1], rect_vertices[rect_indices[i + 1]][1]], color, linewidth=2)

# Function to plot atoms
def plot_atoms(offset, V1, V2, d1, d2, color1, color2):
    # Red atoms
    plt.plot(offset[0] + d1[0], offset[1] + d1[1], color1, markersize=10)
    plt.plot(offset[0] + d1[0] + V1[0], offset[1] + d1[1] + V1[1], color1, markersize=10)
    plt.plot(offset[0] + d1[0] + V2[0], offset[1] + d1[1] + V2[1], color1, markersize=10)
    plt.plot(offset[0] + d1[0] + V1[0] + V2[0], offset[1] + d1[1] + V1[1] + V2[1], color1, markersize=10)
    plt.plot(offset[0] + a * np.cos(np.radians(60)), offset[1] + a * np.sin(np.radians(60)), color1, markersize=10)

    # Green atoms
    plt.plot(offset[0] + d2[0], offset[1] + d2[1], color2, markersize=10)
    plt.plot(offset[0] + d2[0] + V1[0], offset[1] + d2[1] + V1[1], color2, markersize=10)
    plt.plot(offset[0] + a * np.cos(np.radians(60)), offset[1] + a * np.sin(np.radians(60)) + d2[1], color2, markersize=10)

# Function to calculate angles between bonds
def calculate_angles(bonds):
    angles = []
    for i in range(len(bonds)):
        for j in range(i + 1, len(bonds)):
            common_atom = None
            if np.array_equal(bonds[i][0], bonds[j][0]):
                common_atom = bonds[i][0]
                vec1 = bonds[i][1] - common_atom
                vec2 = bonds[j][1] - common_atom
            elif np.array_equal(bonds[i][0], bonds[j][1]):
                common_atom = bonds[i][0]
                vec1 = bonds[i][1] - common_atom
                vec2 = bonds[j][0] - common_atom
            elif np.array_equal(bonds[i][1], bonds[j][0]):
                common_atom = bonds[i][1]
                vec1 = bonds[i][0] - common_atom
                vec2 = bonds[j][1] - common_atom
            elif np.array_equal(bonds[i][1], bonds[j][1]):
                common_atom = bonds[i][1]
                vec1 = bonds[i][0] - common_atom
                vec2 = bonds[j][0] - common_atom

            if common_atom is not None:
                cos_angle = np.dot(vec1, vec2) / (np.linalg.norm(vec1) * np.linalg.norm(vec2))
                cos_angle = np.clip(cos_angle, -1, 1)  # Ensure cos_angle is within the valid range
                angle = np.arccos(cos_angle) * (180 / np.pi)
                # Validate angle deviation
                if np.abs(angle) > 0.1:  # Include only realistic angles
                    angles.append(angle)
    return angles

# Function to plot carbon-carbon bonds and calculate distances
def plot_carbon_bonds(basis_atoms_red, basis_atoms_green):
    distances = []
    bonds = []  # Store the bonds to calculate angles later
    for red_atom in basis_atoms_red:
        for green_atom in basis_atoms_green:
            red_atom_np = np.array(red_atom)
            green_atom_np = np.array(green_atom)
            distance = np.linalg.norm(red_atom_np - green_atom_np)
            if distance < a + 0.1:
                distances.append(distance)
                bonds.append((red_atom_np, green_atom_np))
                plt.plot([red_atom[0], green_atom[0]], [red_atom[1], green_atom[1]], 'k-')

    return distances, bonds

def generate_basis_atoms(offset, V1, V2, d1, d2):
    basis_atoms_red = [
        offset + origin,
        offset + V1,
        offset + 3 * d2,
        offset + V1 + 3 * d2,
        offset + np.array([a * np.cos(np.radians(60)), a * np.sin(np.radians(60))])
    ]

    basis_atoms_green = [
        offset + d2,
        offset + d2 + V1,
        offset + np.array([a * np.cos(np.radians(60)), a * np.sin(np.radians(60)) + d2[1]])
    ]

    return basis_atoms_red, basis_atoms_green

# Function to plot atoms and lattice points
def plot_atoms_and_lattice(supercell_counter, vertical_extension_counter, V1, V2, d1, d2):
    plt.xlabel('x')
    plt.ylabel('y')
    plt.grid(True)
    plt.axis('equal')

    all_red_atoms = set()
    all_green_atoms = set()

    # Generate and plot lattice points for the supercell
    for i in range(-supercell_counter, supercell_counter + 1):
        for j in range(-vertical_extension_counter, vertical_extension_counter + 1):
            offset = np.array([i * V1[0] + j * V2[0], i * V1[1] + j * V2[1]])
            plt.plot(offset[0], offset[1], 'ko')  # Lattice points
            plot_atoms(offset, V1, V2, d1, d2, 'ro', 'go')
            red_atoms, green_atoms = generate_basis_atoms(offset, V1, V2, d1, d2)
            all_red_atoms.update(map(tuple, red_atoms))
            all_green_atoms.update(map(tuple, green_atoms))

    # Plot the central unit cell
    plot_rectangle(origin, V1, d2, 'blue')
    plot_atoms(origin, V1, V2, d1, d2, 'ro', 'go')

    # Plot the carbon-carbon bonds considering the entire supercell
    distances, bonds = plot_carbon_bonds(list(all_red_atoms), list(all_green_atoms))

    return distances, bonds, list(all_red_atoms), list(all_green_atoms)

# Function to calculate total energy
def calculate_energy(distances, bonds):
    total_energy = 0
    eq_distance = 0.824  # Equilibrium distance for bond length
    for distance in distances:
        total_energy += 0.5 * K * round((distance - eq_distance), 3) ** 2  # Energy contribution from bond elongation

    angles = calculate_angles(bonds)
    for angle in angles:
         angle_deviation = angle - ideal_angle
         total_energy += 0.5 * angle_constant * angle_deviation ** 2  # Energy contribution from angle deviation

    return total_energy

# Function to dynamically update lattice vectors and dependent vectors
def update_lattice_vectors(a):
    d2 = np.array([0, (1 / 3 ** 0.5) * a])
    V1 = np.array([a, 0])
    V2 = np.array([0, 3 * d2[1]])
    d1 = np.array([0, 0])
    return V1, V2, d1, d2

# Example usage: plot with horizontal supercell counter and vertical extension counter
horizontal_supercell_counter = 0
vertical_extension_counter = 0
a = 1.428  # Initial lattice constant
V1, V2, d1, d2 = update_lattice_vectors(a)
distances, bonds, all_red_atoms, all_green_atoms = plot_atoms_and_lattice(horizontal_supercell_counter, vertical_extension_counter, V1, V2, d1, d2)
plot_vectors([3 * d2, V1], [0, 0], 'blue')

# Generate lattice points for the central unit cell
lattice_points = []
for i in range(-horizontal_supercell_counter - 1, horizontal_supercell_counter + 3):
    for j in range(-vertical_extension_counter - 1, vertical_extension_counter + 3):
        lattice_points.append((i * V1[0] + j * V2[0], i * V1[1] + j * V2[1]))

for point in lattice_points:
    plt.plot(point[0], point[1], 'ko')

angles = calculate_angles(bonds)
energy = calculate_energy(distances, bonds)
plt.title(f'Graphene Lattice - Supercell VisualizationnTotal Energy: {energy:.4f} (only bond elongation for now)')
print("Distances:", len(distances))
print("Angles:", len(angles))

# Print coordinates of all atoms
print("Atom Coordinates (X, Y):")

all_atom_coords = list(all_red_atoms) + list(all_green_atoms)
all_atom_coords = [list(coord) for coord in all_atom_coords]

print("Number of atoms:", len(all_atom_coords))
print("Atom Coordinates:", all_atom_coords)
plt.show()


# Calculation and plotting of energy versus lattice constant
energy_values = []
eq_distance_values = []
a_values = np.arange(2, 10, 0.1)
for a in a_values:
    a = np.round(a,3)
    print(f"Lattice constant: {a}")
    V1, V2, d1, d2 = update_lattice_vectors(a)
    distances, bonds, all_red_atoms, all_green_atoms = plot_atoms_and_lattice(horizontal_supercell_counter, vertical_extension_counter, V1, V2, d1, d2)
    energy = calculate_energy(distances, bonds)
    print(energy)
    energy_values.append(energy)
    eq_distance_values.append(np.mean(distances))  # Calculate the average distance for equilibrium distance

# Plotting the energy versus lattice constant
fig, ax = plt.subplots(figsize=(7, 5))
ax.plot(a_values, energy_values, 'ro', label='Calculated Energies')
p_fit = np.poly1d(np.polyfit(a_values, energy_values, 2))
ax.plot(a_values, p_fit(a_values), label='Quadratic Fit')
K_squared_constant = np.round((np.polyfit(a_values, energy_values, 2)[0]), 3)
ax.set_title(f'Total Energy vs Lattice Constant nQuadratic Fit: Coefficient of K^2 = {K_squared_constant:.4f} [eV*A^-2]')
ax.set_xlabel('Lattice Constant (a)')
ax.set_ylabel('Total Energy (eV)')
ax.legend()
ax.grid(True)

plt.show()

I attempted to simulate energy calculations for a graphene structure using a predefined constant (K = 63.9) in my code. I expected the energy calculations to yield consistent results with K remaining unchanged. However, upon plotting Energy versus Lattice Constant (a), I found that the calculated constant K deviated unexpectedly, showing a multiplication factor of approximately 1.1667 (resulting in K = 74.5520). This discrepancy is puzzling as I can’t identify any source in my script that accounts for this factorization.

New contributor

Itay Biton is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật