Как я могу получить доступ к соседним элементам матрицы, используя NumPy? - PullRequest
0 голосов
/ 28 сентября 2019

Я сделал код, который рассчитывает растворение жидкостей, проблема в том, что код очень плохой, поэтому я смотрел на это с NumPy, я могу оптимизировать его, но я застрял в течение нескольких часов, не зная, каквыполните следующий код, используя numpy и функцию roll.В основном у меня есть матрица, что индекс и не может быть больше 1024, для этого я использую%, чтобы вычислить, что это за индекс.Но это занимает много времени.

Я пытался использовать numpy, использовать roll, вращать матрицу, и тогда мне не нужно вычислять модуль.Но я не знаю, как воспринимать ценности соседей.

def evolve(grid, dt, D=1.0):
  xmax, ymax = grid_shape
  new_grid = [[0.0,] * ymax for x in range(xmax)]
  for i in range(xmax):
    for j in range(ymax):
      grid_xx = grid[(i+1)%xmax][j] + grid[(i-1)%xmax][j] - 2.0 * grid[i][j]
      grid_yy = grid[i][(j+1)%ymax] + grid[i][(j-1)%ymax] - 2.0 * grid[i][j]
      new_grid[i][j] = grid[i][j] + D * (grid_xx + grid_yy) * dt
  return new_grid 

1 Ответ

0 голосов
/ 28 сентября 2019

Вы должны переписать функцию evolve с (почти) нуля, используя numpy.

Вот рекомендации:

  • Во-первых, grid должно быть 2Dnumpy array, а не список списков.
  • Ваш учитель предложил функцию roll: посмотрите на docs и попытайтесь понять, как она работает.roll решит проблему поиска соседних записей в матрице, сдвинув (или перевернув) матрицу по одной из осей.Затем вы можете создать сдвинутые версии grid в четырех направлениях и использовать их вместо поиска соседей.
  • Как только вы получите сдвинутые grid s, вы увидите, что вам не понадобятсядля циклов для расчета каждой ячейки new_grid: вы можете использовать векторизованный расчет, который быстрее.

Таким образом, код будет выглядеть так:

def evolve(grid, dt, D=1.0):
    if not isinstance(grid, np.ndarray): #ensuring that is a numpy array.
        grid = np.array(grid)
    u_grid = np.roll(grid, 1, axis=0)
    d_grid = np.roll(grid, -1, axis=0)
    r_grid = np.roll(grid, 1, axis=1)
    l_grid = np.roll(grid, -1, axis=1)
    new_grid = grid + D * (u_grid + d_grid + r_grid + l_grid - 4.0*grid) * dt
    return new_grid

С 1024x 1024 матрицы, каждый numpie evolve занимает (на моей машине) ~ 0,15 секунды, чтобы вернуть new_grid.Ваша evolve с циклами for занимает ~ 3,85 секунды.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...