хранение матриц, вычисленных из двух для циклов (добавление списка не работает)

я реализую итерационный метод Якоби

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

Мне нужно вычесть и оперировать этими матрицами для критериев сходимости

# Iterate Jacobi until convergence  
U = np.array([[8.9,8.9,8.9,8.9,8.9],[8.4,0,0,0,9.2],[7.2,0,0,0,9.4],[6.1,6.8,7.7,8.7,6.1]])
UI=U
UF=U
UFK=[]
k=0
while k<3:
    k=k+1 # update the iteration counter
    for i in range (1,Nx-1):
        for j in range (1,Ny-1):
            UF[j,i] = (UI[j+1,i]+UI[j,i+1]+UI[j-1,i]+UI[j,i-1])*0.25 #the matrix i want to store after each iteration 
    UFK.append(UF) # 
    print (UF) # when i print UF i get the correct matrix at each iteration displayed 

[[ 8.9         8.9         8.9         8.9         8.9       ]
 [ 8.4         4.325       3.30625     5.3515625   9.2       ]
 [ 7.2         4.58125     3.896875    6.83710938  9.4       ]
 [ 6.1         6.8         7.7         8.7         6.1       ]]
[[ 8.9         8.9         8.9         8.9         8.9       ]
 [ 8.4         6.296875    6.11132812  7.76210937  9.2       ]
 [ 7.2         6.0484375   6.67421875  8.13408203  9.4       ]
 [ 6.1         6.8         7.7         8.7         6.1       ]]
[[ 8.9         8.9         8.9         8.9         8.9       ]
 [ 8.4         7.36494141  7.67531738  8.47734985  9.2       ]
 [ 7.2         7.00979004  7.62979736  8.5517868   9.4       ]
 [ 6.1         6.8         7.7         8.7         6.1       ]]

print(UFK) # when i display the appended UFK it is just repeating a single matrix 3 times

[array([[ 8.9       ,  8.9       ,  8.9       ,  8.9       ,  8.9       ],
        [ 8.4       ,  7.36494141,  7.67531738,  8.47734985,  9.2       ],
        [ 7.2       ,  7.00979004,  7.62979736,  8.5517868 ,  9.4       ],
        [ 6.1       ,  6.8       ,  7.7       ,  8.7       ,  6.1       ]]),
 array([[ 8.9       ,  8.9       ,  8.9       ,  8.9       ,  8.9       ],
        [ 8.4       ,  7.36494141,  7.67531738,  8.47734985,  9.2       ],
        [ 7.2       ,  7.00979004,  7.62979736,  8.5517868 ,  9.4       ],
        [ 6.1       ,  6.8       ,  7.7       ,  8.7       ,  6.1       ]]),
 array([[ 8.9       ,  8.9       ,  8.9       ,  8.9       ,  8.9       ],
        [ 8.4       ,  7.36494141,  7.67531738,  8.47734985,  9.2       ],
        [ 7.2       ,  7.00979004,  7.62979736,  8.5517868 ,  9.4       ],
        [ 6.1       ,  6.8       ,  7.7       ,  8.7       ,  6.1       ]])]

2 ответа

  1. Вы должны установить размер UFK, прежде чем добавить его, или вы всегда копируете одну и ту же матрицу несколько раз. Следующий код может генерировать выходные данные правильно:

    UFK = np.array([]).reshape(0,5)
    k = 0
    while k < 3:
        k += 1
        for i in range(1, Nx-1):
            for j in range(1, Ny-1):
                UF[j, i] = (UI[j+1, i] + UI[j, i+1] + UI[j-1, i] + UI[j, i-1]) * 0.25
        UFK = np.append(UFK, UF, axis=0)
    

    Другой способ добавить массивUFK = np.vstack((UFK, UF)), который даст вам тот же результат.

  2. UI=U  # why?  UI is not a copy of U, it IS U
    # UF=U  # another why?  Changes of UF will change UI and U as well
    UFK=[]    # appending to a list is great
    k=0
    while k<3:
        k=k+1 # update the iteration counter
        UF = np.zeros_like(U)  # a fresh copy for iteration
        for i in range (1,Nx-1):
            for j in range (1,Ny-1):
                UF[j,i] = (UI[j+1,i]+UI[j,i+1]+UI[j-1,i]+UI[j,i-1])*0.25 
        UFK.append(UF) # 
        print (UF) 
    print(UFK)
    

    UFK теперь должен быть список k UFмассивов.

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

    Но, если подумать, возможно, изменение UIявляется частью плана. Если да, то зачем скрывать этот факт переменными UFиUI? В этом случае вы можете собрать промежуточные итерации с a U.copy()— то есть сохранить копию Uв список, а не саму Uсебя.

    for i... :
       for j....:
            U[j,i] = (U[j+1,i]+U[j,i+1]+U[j-1,i]+U[j,i-1])*0.25 
    UFK.append(U.copy())
    print (U)
    

    Список содержит указатели на объекты. Если я напишу

    alist = [U, U, U]
    U[0,0] = 10000
    

    это 10000будет отображаться во всех 3 элементах списка-потому что они одно и то же.

    В коде вы обращаетесь UFк списку, а затем изменяете его на каждой итерации. В результате список содержит только kуказатели на один и тот же массив.