Я выполняю некоторые МД симуляции с участием систем миллионов атомов.
Я написал некоторый код для генерации файла, который представляет собой просто список координат атома XYZ. Теперь мне нужно создать связи между атомами. Если два атома находятся на определенном расстоянии друг от друга, это считается связью.
Пример файла XYZ:
1 0 0
2 0 0
7 0 0
10 0 0
9 0 0
Итак, у меня есть пять атомов. Если мой порог расстояния составляет 2 единицы, то мой список облигаций будет:
1 2
3 5
4 5
(где числа соответствуют индексу координаты в файле XYZ).
Наивный подход к созданию этого списка просто:
for i = 1:numAtoms
for j = i+1:numAtoms
if distance(atom[i], atom[j]) < 2
bonds.push [i, j]
Тем не менее, это быстро достигает алгоритмического предела и является медленным даже при высоко оптимизированном C для миллионов атомов, по крайней мере, так часто, как я буду делать этот процесс.
Единственный опыт, который у меня есть с структурами данных с пространственным разделением, это kd-деревья, когда я однажды написал фотонную карту, поэтому я не знаю, как лучше всего решить эту проблему. Я уверен, что, вероятно, есть что-то оптимальное для этого.
Я должен также упомянуть, что мой блок моделирования является периодическим, что означает, что атом в точке (0,5, 0, 0) будет связан с атомом в точке (boxWidth — 0,5, 0, 0) с пороговым расстоянием, например 2.
Простые решения первыми попробуют. Они быстро кодируются и легко тестируются. Если это не дает вам требуемой производительности, затем Вы можете попробовать что-то более хитрое.
Таким образом, вы можете серьезно сократить пространство поиска, назначив координаты сетки вашим атомам. Ничего технического. Как октрие бедняка …
Все, что вам нужно сделать, это иметь размер сетки 2 и искать все атомы в локальной сетке и каждой соседней сетке. Очевидно, что сетка 3D. Расположение сетки атома не сложнее, чем деление каждой его координаты на размер сетки.
Очевидно, вы делаете предварительный проход и создаете список (или вектор) атомов, принадлежащих каждой ячейке. Вы можете хранить списки в map
индексируется по координатной сетке 3D. Затем для каждого атома вы можете просто просмотреть локальные списки и выполнить тесты связи.
Кроме того, не используйте квадратный корень для вашего расстояния. Вместо этого используйте квадрат расстояния. Это сэкономит нагрузку на обработку.
Других решений пока нет …