/ / Ising Модель: Як скоротити час моделювання? - python, масиви, numpy, індексація

Модель Ісінга: Як скоротити час моделювання? - python, масиви, numpy, індексація

Я моделюю Модель Ісінга феромагнетиків розмірами вище 3, використовуючи просту структуру кодування, але мають деякі проблеми з ефективністю. У моєму коді є одна особлива функція, яка є вузьким місцем.

У процесі моделювання необхіднознайти те, що називають найближчими сусідами даного сайту. Наприклад, у 2D-моделі Ising спини займають решітку в кожній точці, позначеної двома числами: (x, y). Найближчими сусідами точки в (x, y) є чотири суміжні значення, а саме (x + 1, y), (x-1, y), (x, y + 1), (x, y-1) . У 5D спин на деякому сайті решітки має координати (a, b, c, d, e) з 10 найближчими сусідами, у тій же формі, що і раніше, але для кожної точки в кортежі.

Тепер тут знаходиться код, на який наведено наступні входи:

"site_i is a random value between 0 and n-1 denoting the site of the ith spin"
"coord is an array of size (n**dim,dim) that contains the coordinates of ever spin"
"spins is an array of shape (n**dim,1) that contains the spin values (-1 or 1)"
"n is the lattice size and dim is the dimensionality"
"neighbor_coupling is the number that tells the function to return the neighbor spins that are one spacing away, two spacing away, etc."

def calc_neighbors(site_i,coord,spins,n,dim,neighbor_coupling):
# Extract all nearest neighbors
# Obtain the coordinates of each nearest neighbor
# How many neighbors to extract
num_NN = 2*dim
# Store the results in a result array
result_coord = np.zeros((num_NN,dim))
result_spins = np.zeros((num_NN,1))
# Get the coordinates of the ith site
site_coord = coord[site_i]
# Run through the + and - for each scalar value in the vector in site_coord
count = 0
for i in range(0,dim):
assert count <= num_NN, "Accessing more than nearest neighbors values."
site_coord_i = site_coord[i]
plus = site_coord_i + neighbor_coupling
minus = site_coord_i - neighbor_coupling

# Implement periodic boundaries
if (plus > (n-1)): plus = plus - n
if (minus < 0): minus = n - np.abs(minus)

# Store the coordinates
result_coord[count] = site_coord
result_coord[count][i] = minus
# Store the spin value
spin_index = np.where(np.all(result_coord[count]==coord,axis=1))[0][0]
result_spins[count] = spins[spin_index]
count = count + 1

# Store the coordinates
result_coord[count] = site_coord
result_coord[count][i] = plus
# Store the spin value
spin_index = np.where(np.all(result_coord[count]==coord,axis=1))[0][0]
result_spins[count] = spins[spin_index]
count = count + 1

Я не знаю, як я можу зробити це швидше, але це дуже допоможе. Можливо, інший спосіб зберігати все?

Відповіді:

0 для відповіді № 1

Не відповідь, лише деякі пропозиції для випрямлення: багато копіювань під час спроби документувати кожен крок розрахунку. Не жертвуючи цим, ви можете впасти site_coord_i, і потім

    # New coords, implement periodic boundaries
plus = (site_coord[i] + neighbor_coupling) % n
minus = (site_coord[i] - neighbor_coupling + n) % n

Це дозволяє уникнути проміжних кроків ("якщо ..."). Ще однією пропозицією було б відкласти використання підмасу, поки не дійсно потрібно:

    # Store the coordinates
rcc = site_coord
rcc[i] = plus
# Store the spin value
spin_index = np.where(np.all(rcc==coord,axis=1))[0][0]
result_spins[count] = spins[spin_index]
result_coord[count] = rcc
count += 1

Мета полягає в тому, щоб зменшити кількість розмірів змінної, що використовується в порівнянні, і віддати перевагу локальним змінним.