2012-03-13 3 views
3

В действительности проблема заключается в том, что я пытаюсь взять список позиций атомов в элементарной ячейке и построить соответствующую суперячейку, учитывая, сколько раз повторять ячейки в каждом направлении.Неожиданное поведение при обновлении 3D-массива

Это приводит к структуре петли:

#Create Every Unit Cell in SuperCell 
aNum=2 
bNum=2 
cNum=2 
atomPos = copy.deepcopy(atomPositions) 
for l in range(len(atomPos)): 
    index=0 
    for i in range(cNum): 
     for j in range(bNum): 
      for k in range(aNum): 
       for _ in range(numEachAtom[l]): 
        atomPositions[l][index][0] = atomPos[l][index][0] + 1*k 
        atomPositions[l][index][1] = atomPos[l][index][1] + 1*j 
        atomPositions[l][index][2] = atomPos[l][index][2] + 1*i 
        print atomPositions[0][0] 
        index += 1 

Где atomPositions является 3D-массив таким образом, что: atomPositions[atomtype=l][atom=index][atomposition=0] = [x,y,z] и оператор печати для диагностических целей.

Проблема в том, что из заявления печати кажется, что atomPositions[0][0] изменяется чаще, чем тип атома, и, как кажется, индекс обновляется правильно, я просто этого не понимаю.

Почему atomPositions[0][0] меняется чаще, чем l?

Первоначально я столкнулся с проблемой изменения списка, который вы повторяете, отсюда и глубокая копия с самого начала. Любые комментарии были бы высоко оценены!

P.S. Это мой первый раз, задавая вопрос, и я полный новичок в Python, поэтому, пожалуйста, не стесняйтесь комментировать мое отсутствие форматирования/ясность/стиль и т.д.

Edit: Пример начала выход для numEachAtom=[4,6]:

[0.17611251675504244, 0.17611251675504244, 0.17611251675504244] 
[0.17611251675504244, 0.17611251675504244, 0.17611251675504244] 
[0.17611251675504244, 0.17611251675504244, 0.17611251675504244] 
[0.17611251675504244, 0.17611251675504244, 0.17611251675504244] 
[1.1761125167550424, 0.17611251675504244, 0.17611251675504244] 
[1.1761125167550424, 0.17611251675504244, 0.17611251675504244] 
[1.1761125167550424, 0.17611251675504244, 0.17611251675504244] 
[1.1761125167550424, 0.17611251675504244, 0.17611251675504244] 
[0.17611251675504244, 1.1761125167550424, 0.17611251675504244] 
[0.17611251675504244, 1.1761125167550424, 0.17611251675504244] 
[0.17611251675504244, 1.1761125167550424, 0.17611251675504244] 

т.д.

Edit: Как atomPositions инициализируется:

#Separate out positions of different atom types 
atomPositions = [] 
counter=0 
for i,atomN in enumerate(numEachAtom):   
    atomPositions.append(origAtomPositions[counter:counter+atomN]) 
    counter += atomN 

Edit: зависимости и т.д.

import sys 
import scipy as sp 
from scipy import * 
import copy 

Edit: atomPositions [0] инициализируется в

[[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748] 
[ 0.17611252 0.17611252 0.17611252] 
[ 0.32388748 0.32388748 0.32388748] 
[ 0.42611252 0.42611252 0.42611252] 
[ 0.07388748 0.07388748 0.07388748]] 
+1

Эй, это очень хороший вопрос! Было бы полезно предоставить краткий пример вывода, чтобы люди могли понять, что ваша проблема в конкретном случае. – Marcin

+1

Как вы инициализируете 'atomPositions'? – sth

+1

Можете ли вы предоставить рабочий пример для содержимого списков? –

ответ

1

Это выглядит так, как если бы вы где-то умножали ваш список входных данных. Поскольку это вложенный список, он не будет делать то, что вы хотите.

+0

Не могу поверить, что я этого не видел, но я нашел преступника. Тем не менее, я считаю это поведение совершенно противоречивым. Спасибо всем, кто потратил на это время. '# Expand for Extra Atoms для i в диапазоне (len (atomPositions)): atomPositions [i] * = aNumber * bNumber * cNumber' – TCTopCat

+0

Я предположил, что за пределами опубликованного кода должно произойти что-то, о поведении, о котором вы сообщали. – neil

0

atomPositions[0][0] будет меняться несколько раз, это то, что ваш for _ in range(numEachAtom[l]) делает.

Что это за цикл в любом случае? Разве вы не можете просто написать

#Create Every Unit Cell in SuperCell 
aNum=2 
bNum=2 
cNum=2 
atomPos = copy.deepcopy(atomPositions) 
for l in range(len(atomPos)): 
    index=0 
    for i in range(cNum): 
     for j in range(bNum): 
      for k in range(aNum): 
       atomPositions[l][index][0] = atomPos[l][index][0] + numEachAtom[l]*k 
       atomPositions[l][index][1] = atomPos[l][index][1] + numEachAtom[l]*j 
       atomPositions[l][index][2] = atomPos[l][index][2] + numEachAtom[l]*i 
       print atomPositions[0][0] 

Edit: оп просто обновил свой код, где он вставляется индекс в цикле, так что это не имеет смысла больше.

1

Я использую как itertools, так и numpy здесь, две очень полезные библиотеки, с которыми вам следует познакомиться. Возникает вопрос:

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

Ответы ниже, в общем случае для любого измерения.Для иллюстративных целей я использую 2D-массив, но он будет работать нормально, если вы передадите ему 3D-массив. Квадратный цикл, который вы используете в своем сообщении, заменяется одним контуром по всем возможным направлениям ячеек с product. Разделите его и поиграйте с ним, чтобы посмотреть, как это работает.

from numpy import * 
from itertools import product 

# Pass in the points, plus a vector that indicates the repeats in each direction 
def supercell(R, v): 
    v = array(v) + 1 
    n,d = R.shape 

    # Construct the copy directions 
    CV = list(product(*map(range,v))) 
    R2 = zeros((len(CV)*n,d)) 

    for i,cell in enumerate(CV): 
     R2[i*n:(i+1)*n,:] = cell+R 
    return R2 

# Construct some random points within a unit cell to work with 
N,dimension = 100, 2 
# Contrain them so you can see the supercell 
R = random.random((N,dimension))*.6 + .5 

R2 = supercell(R,[2,3]) 

# Plot the results 
from pylab import * 
scatter(*zip(*R2),color='b') 
scatter(*zip(*R),color='r') 
show() 

enter image description here

В вашем примере с копией 2 в каждом положительном направлении, вектор CV будет выглядеть так:

[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2)] 

это магия функции product.

+0

Большое спасибо, это должно быть очень полезно. У меня определенно будет игра с этим позже. Если у вас есть какие-то идеи, я буду признателен за любые комментарии о том, почему код, опубликованный в вопросе, действует так странно? – TCTopCat

+0

@TCTopCat Сначала я попытался, но я не понимаю, почему вам нужны три отдельных индекса. То, что я вижу, начинается с самой внутренней: (x, y, z) демаркации, а затем индекса атома. Внешний индекс большинства не имеет смысла. В приведенном выше примере моя суперобложка имеет форму '(N, 3)' где 'N' - новое число атомов. В ваших примерах есть '(x, N, 3)'. Что такое 'x'? – Hooked

+0

Первый индекс атомных позиций относится к типу атома. Он немного запутан, но для целей моих входных файлов (в пакет моделирования функциональной теории плотности, называемый [VASP] (http://www.vasp.at/)). Мне нужно сделать это разделение, чтобы гарантировать, что новый атомный позиции записываются в файл в группах одного и того же элемента. – TCTopCat

Смежные вопросы