Основная идея довольно проста. Вы организуете матрицу ( ), которая представляет «узлы» или вершины в вашей системе. С каждым из этих узлов связано скалярное «напряжение», которое может быть изменено или обновлено по мере выполнения алгоритма. Также будет два узла, напряжение которых не может быть изменено. Мы собираемся применить своего рода «батарею» здесь, чтобы эти два узла представляли два конца этой батареи.V
Отдельно две другие матрицы ( и R h ) представляют ребра в системе, горизонтальную и вертикальную. Это ваши значения сопротивления, я думаю. Я не уверен, как вы собираетесь заполнить их. Но это твоя проблема. Этот метод предполагает, что вы также можете заполнить эти матрицы.RvRh
В зависимости от используемого вами компьютерного языка вы можете или не сможете использовать отрицательные индексы. Не имеет значения Это просто вопрос того, с чем вы столкнулись.
Давайте предположим, что длина разделена на N L секций, а «длина» A разделена на N A секций. Затем вам нужно будет построить матрицу с ( N L + 1 ) ⋅ ( N A + 1 ) вершинами для значений скалярного напряжения. (или больше.) Вам также понадобятся эти две другие матрицы с N A ⋅ ( N L + 1 ) вертикальными ребрами и N L ⋅ ( N A + 1).LNLANA(NL+1)⋅(NA+1)NA⋅(NL+1) горизонтальные ребра между этими вершинами.NL⋅(NA+1)
Сейчас. Инициализировать все вершины с . Выберите одну из вершин слева (желательно посередине) и отметьте ее как 00VЗначение V , которое НЕ допускается изменять. Используйте любой метод, который вы хотите для этого. Выберите одну из вершин справа (желательно посередине) и измените ее значение на 10V , снова принимая к сведению, что его значение никогда не может измениться. Техника, которая работает здесь, состоит в том, чтобы просто позволить этому измениться нормально, но затем заменить значение на каждом шаге. Но не имеет значения, как вы этого достигнете, пока вы этого достигнете.1V
(Существуют и другие методы по соображениям эффективности. Но, вероятно, здесь не стоит их использовать.)
Теперь о алгоритме, который иногда называют шахматной доской или красно-черным алгоритмом. Перемещаясь по матрице напряжения вашего узла, обработайте каждый узел, в котором сумма двух индексов, является четной, выполняя следующее простое назначение:i+j
Vi,j=Rhi,j−1⋅Rhi,j⋅(Vi−1,j⋅Rvi,j+Vi+1,j⋅Rvi−1,j)Rhi,j−1⋅Rhi,j⋅(Rvi,j+Rvi−1,j)+Rvi−1,j⋅Rvi,j(Rhi,j+Rhi,j−1)+Rvi−1,j⋅Rvi,j⋅(Vi,j−1⋅Rhi,j+Vi,j+1⋅Rhi,j−1)Rhi,j−1⋅Rhi,j⋅(Rvi,j+Rvi−1,j)+Rvi−1,j⋅Rvi,j(Rhi,j+Rhi,j−1)
Вышеупомянутое уравнение является не чем иным, как вычислением напряжения центрального узла, имеющего четыре резистора, подключенного к нему, где известны напряжения на других концах четырех резисторов. Напряжение центрального узла затем вычисляется из вышеприведенного уравнения. Поскольку делитель одинаков для каждого члена, вы можете просто вычислить сумму числителей и затем разделить один раз на знаменатель.
Это обновит все узлы, где сумма является четной. Теперь вы выполняете ту же процедуру для всех узлов, где сумма i + j нечетна. После выполнения обоих этих шагов вы завершили один цикл.i+ji+j
При необходимости сбросьте два специальных узла (для и для 10V как обсуждалось ранее.) Или, если вы защитили эти два узла, нет необходимости сбрасывать их.1V
Вы готовы к следующему циклу. Выполняйте эти циклы столько раз, сколько считаете необходимым для общего состояния (и так будет).
Когда вы останавливаете процесс, вы можете легко определить сопротивление, либо выбрав просмотр узлов, окружающих ваш защищенный узел слева, либо просмотр узлов, окружающих защищенный узел справа. (Это может быть хорошей идеей сделать вашу матрицу достаточно увеличенной [на 1 во всех направлениях], чтобы у вас на самом деле было четыре узла, окружающих любой выбор.) Разница напряжений между окружающими узлами и специальным узлом, деленная на Сопротивление по краям между ними говорит вам текущий выход / вход в ваш специальный узел. Поскольку это «батарейный» узел, этот ток должен быть ВСЕМ тока. Поскольку напряжение составляет , по определению, деление 1 на сумму этих четырех токов, которые вы найдете, говорит вам об общем сопротивлении.1V
Я смотрю на некоторый код, который я написал, в сумме с множеством комментариев, всего 67 строк. Так что это не сложно писать.
«Краткое резюме» этой идеи заключается в том, что вы применяете батареи, а затем смотреть, как напряжение распространяется по всей системе. Как только напряжение стабилизируется (ваши критерии для этого), все, что вам нужно сделать, это посмотреть на ток, входящий или выходящий из одной клеммы аккумулятора или другой. Они оба должны иметь одинаковое текущее значение (в некоторых числовых пределах) по понятным причинам.1V
Почему вы должны разделить систему на i + j = четное и i + j = нечетное?
V5,5=f(V4,5,V6,5,V5,4,V5,6)V5,5V5,6=f(V4,6,V6,6,V5,5,V5,7)V5,5V5,7=f(V4,7,V6,7,V5,6,V5,8)потому что ни один из входов в функцию не является узлами, которые были изменены во время этого шага. Затем вы качаетесь и вычисляете альтернативы, избегая появления пятен, но теперь обновляете альтернативы. Вы действительно должны сделать это таким образом.
Кроме того, идентична ли формула для четных и нечетных шагов?
Да, это то же самое.
Можно ли все это решить за один шаг, используя некую линейную систему Ax = b, где A - линейный оператор, а b - граничные условия? Глядя на это, это кажется несколько аналогичным конечно-разностным методам для решения уравнений в частных производных ..
Есть связь. Я думаю, что это называется реализацией без матрицы.
Вот пример. Следующий набор значений резисторов был помещен в LTSpice для моделирования:
1V30.225mA30.224552mA
Я запустил следующую программу VB.NET:
Module GEOGRID
Const NL As Integer = 2
Const NA As Integer = 2
Const INF As Double = 1.0E+32
Sub Main()
Static Rh As Double(,) = New Double(NL + 2, NA + 1) {
{INF, INF, INF, INF},
{INF, 5, 21, INF},
{INF, 76, 10, INF},
{INF, 32, 22, INF},
{INF, INF, INF, INF}}
Static Rv As Double(,) = New Double(NA + 1, NL + 2) {
{INF, INF, INF, INF, INF},
{INF, 61, 50, 16, INF},
{INF, 56, 45, 18, INF},
{INF, INF, INF, INF, INF}}
Dim V As Double(,) = New Double(NL + 2, NA + 2) {
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 1, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}}
Dim PDE As Func(Of Integer, Integer, Double) = Function(ByVal i As Integer, ByVal j As Integer) (
Rh(i, j - 1) * Rh(i, j) * (V(i - 1, j) * Rv(i, j) + V(i + 1, j) * Rv(i - 1, j)) +
Rv(i - 1, j) * Rv(i, j) * (V(i, j - 1) * Rh(i, j) + V(i, j + 1) * Rh(i, j - 1))
) / (
Rh(i, j - 1) * Rh(i, j) * (Rv(i, j) + Rv(i - 1, j)) +
Rv(i - 1, j) * Rv(i, j) * (Rh(i, j) + Rh(i, j - 1))
)
Dim IV As Func(Of Integer, Integer, Double) = Function(ByVal i As Integer, ByVal j As Integer) 0 +
(V(i, j) - V(i - 1, j)) / Rv(i - 1, j) + (V(i, j) - V(i + 1, j)) / Rv(i, j) +
(V(i, j) - V(i, j - 1)) / Rh(i, j - 1) + (V(i, j) - V(i, j + 1)) / Rh(i, j)
Dim idx As Integer = NA \ 2 + 1
Dim jdx1 As Integer = NL + 1
Dim jdx2 As Integer = 1
For x As Integer = 1 To 1000
For k As Integer = 0 To (NA + 1) * (NL + 1) - 1 Step 2
Dim i As Integer = k \ (NL + 1)
Dim j As Integer = k - i * (NL + 1) + 1
i += 1
If Not (i = idx AndAlso (j = jdx1 OrElse j = jdx2)) Then V(i, j) = PDE(i, j)
Next
For k As Integer = 1 To (NA + 1) * (NL + 1) - 1 Step 2
Dim i As Integer = k \ (NL + 1)
Dim j As Integer = k - i * (NL + 1) + 1
i += 1
If Not (i = idx AndAlso (j = jdx1 OrElse j = jdx2)) Then V(i, j) = PDE(i, j)
Next
Next
Console.WriteLine("R = " & (1.0 / IV(idx, jdx1)).ToString)
Console.WriteLine("R = " & (-1.0 / IV(idx, jdx2)).ToString)
End Sub
End Module
R=33.0856844038614Ω
Вышеупомянутая программа показывает способ настройки резисторов, вертикальных и горизонтальных, а также матрицы напряжения, чтобы упростить некоторые тесты для несуществующих узлов и / или значений резисторов. Таким образом, код немного чище, хотя для него требуются дополнительные элементы массива. (Я просто сделал значения дополнительных резисторов бесконечными по величине.) Просто сравните, как я настроил массивы с тем, как была построена схема, и я думаю, что вы сможете выработать все точное подробности здесь.
Я также взломал резисторы и значения узлов, конечно, не делая это каким-либо образом универсальной программой для чтения таблицы значений. Но эту общность довольно легко добавить. И этот код должен сделать все, что я написал, абсолютно однозначным.
xx
0V1V
(Хорошо. Еще одно заключительное замечание. Это было бы намного лучше нацелено на F # или любой приличный компилятор, нацеленный на массивно параллельную вычислительную систему. Каждый расчет в «красном» или «черном» может выполняться параллельно; совершенно независимо друг от друга. F # делает это тривиальным. Так закодированный в F #, вы можете запустить его на всех доступных ядрах без каких-либо особых действий. Это просто работает. Просто замечание, если вы каким-то образом собираете МНОГО данных и, возможно, захотите взять полное преимущество многоядерной системы.)
КОНЕЦ ПРИМЕЧАНИЕ:
Вывод довольно прост из KCL. Поместите четыре резистора в следующем порядке:
смоделировать эту схему - схема, созданная с использованием CircuitLab
Применить KCL:
VR1+VR2+VR3+VR4V=V1R1+V2R2+V3R3+V4R4∴=(V1R1+V2R2+V3R3+V4R4)(R1∣∣R2∣∣R3∣∣R4)
Немного поиграв с алгеброй, получаю результат, который я использовал в коде.