Метод SOR не сходится

У меня есть решение SOR для 2D Лапласа с условием Дирихле в Python. Если для омеги установлено значение 1,0 (что делает метод Якоби), решение сходится нормально. Но используя данные омеги, целевая ошибка не может быть достигнута, потому что решение в какой-то момент просто сходит с ума, не сходясь. Почему бы не сходиться с данной формулой омега? живой пример на repl.it

from math import sin, exp, pi, sqrt

m = 16

m1 = m + 1
m2 = m + 2
grid = [[0.0]*m2 for i in xrange(m2)]
newGrid = [[0.0]*m2 for i in xrange(m2)]

for x in xrange(m2):
    grid[x][0] = sin(pi * x / m1)
    grid[x][m1] = sin(pi * x / m1)*exp(-x/m1)

omega = 2 #initial value, iter = 0
ro = 1 - pi*pi / (4.0 * m * m) #spectral radius
print "ro", ro
print "omega limit", 2 / (ro*ro) - 2/ro*sqrt(1/ro/ro - 1)


def next_omega(prev_omega):
    return 1.0 / (1 - ro * ro * prev_omega / 4.0)

for iteration in xrange(50):
    print "iter", iteration,
    omega = next_omega(omega)
    print "omega", omega,
    for x in range(1, m1):
        for y in range(1, m1):
            newGrid[x][y] = grid[x][y] + 0.25 * omega * \
                (grid[x - 1][y] + \
                 grid[x + 1][y] + \
                 grid[x][y - 1] + \
                 grid[x][y + 1] - 4.0 * grid[x][y])
    err = sum([abs(newGrid[x][y] - grid[x][y]) \
        for x in range(1, m1) \
        for y in range(1, m1)])
    print err,
    for x in range(1, m1):
        for y in range(1, m1):
            grid[x][y] = newGrid[x][y]
    print

1 ответ

Решение

По моему опыту (но я никогда не тратил время на поиски объяснения), кажется, что конвергенция лучше при использовании так называемой красно-черной схемы обновления внутри той же сетки. Это означает, что вы смотрите на сетку, расположенную на шахматном узоре, и сначала вы обновляете ячейки одного цвета, а затем обновляете ячейки другого цвета.

Если мне что-то подобное с вашим кодом, то оно, похоже, сходится. Значение err был немного изменен, потому что вторая сетка больше не используется:

for iteration in xrange(50):
    print "iter", iteration,
    omega = next_omega(omega)
    err = 0
    print "omega", omega,
    for x in range(1, m1):
        for y in range(1, m1):
            if (x%2+y)%2 == 0: # Only update the 'red' grid cells
                diff = 0.25 * omega * \
                    (grid[x - 1][y] + \
                     grid[x + 1][y] + \
                     grid[x][y - 1] + \
                     grid[x][y + 1] - 4.0 * grid[x][y])

                grid[x][y] = grid[x][y] + diff
                err += diff

    for x in range(1, m1):
        for y in range(1, m1):
            if (x%2+y)%2 == 1: # Only update the 'black' grid cells
                diff = 0.25 * omega * \
                    (grid[x - 1][y] + \
                     grid[x + 1][y] + \
                     grid[x][y - 1] + \
                     grid[x][y + 1] - 4.0 * grid[x][y])

                grid[x][y] = grid[x][y] + diff
                err += diff

    print err

Вероятно, это очень неэффективный способ выбора "красных" и "черных" ячеек сетки, но я надеюсь, что понятно, что происходит таким образом.

Другие вопросы по тегам