From: Nick Downing Date: Thu, 17 Jul 2025 05:22:50 +0000 (+1000) Subject: Make solver sparse, put example set in /examples with all items from https://cdn... X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=13c38030c17db892a77b44e022b3d6986fe5cef0;p=resistor_solver.git Make solver sparse, put example set in /examples with all items from https://cdn.zofzpcb.com/RMatrixExamples/RMatrixExamples.zip converted to 4-colour palette --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b44ef38 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/*.png diff --git a/stillOKfor32_50x50.png b/examples/SlotInPlane.png similarity index 57% rename from stillOKfor32_50x50.png rename to examples/SlotInPlane.png index 7f8b9dd..bf754f3 100644 Binary files a/stillOKfor32_50x50.png and b/examples/SlotInPlane.png differ diff --git a/stillOKfor32_100x100.png b/examples/stillOKfor32.png similarity index 56% rename from stillOKfor32_100x100.png rename to examples/stillOKfor32.png index bac61b8..66824be 100644 Binary files a/stillOKfor32_100x100.png and b/examples/stillOKfor32.png differ diff --git a/examples/stripe1.png b/examples/stripe1.png new file mode 100644 index 0000000..c67161c Binary files /dev/null and b/examples/stripe1.png differ diff --git a/examples/stripe1et.png b/examples/stripe1et.png new file mode 100644 index 0000000..9af8838 Binary files /dev/null and b/examples/stripe1et.png differ diff --git a/stillOKfor32_100x100_trimmed.png b/examples/stripe1thin.png similarity index 51% rename from stillOKfor32_100x100_trimmed.png rename to examples/stripe1thin.png index 368a3d0..d7323e5 100644 Binary files a/stillOKfor32_100x100_trimmed.png and b/examples/stripe1thin.png differ diff --git a/examples/tentacledTriangle.png b/examples/tentacledTriangle.png new file mode 100644 index 0000000..c5fea75 Binary files /dev/null and b/examples/tentacledTriangle.png differ diff --git a/examples/tooBigFor32.png b/examples/tooBigFor32.png new file mode 100644 index 0000000..9dadd2c Binary files /dev/null and b/examples/tooBigFor32.png differ diff --git a/examples/wideStripe.png b/examples/wideStripe.png new file mode 100644 index 0000000..932d0e3 Binary files /dev/null and b/examples/wideStripe.png differ diff --git a/examples/wideStripe_punched.png b/examples/wideStripe_punched.png new file mode 100644 index 0000000..0a12957 Binary files /dev/null and b/examples/wideStripe_punched.png differ diff --git a/n.sh b/n.sh new file mode 100755 index 0000000..1e25e22 --- /dev/null +++ b/n.sh @@ -0,0 +1,10 @@ +#!/bin/sh +./resistor_solver.py examples/SlotInPlane.png SlotInPlane.png +./resistor_solver.py examples/stillOKfor32.png stillOKfor32.png +./resistor_solver.py examples/stripe1et.png stripe1et.png +./resistor_solver.py examples/stripe1.png stripe1.png +./resistor_solver.py examples/stripe1thin.png stripe1thin.png +./resistor_solver.py examples/tentacledTriangle.png tentacledTriangle.png +./resistor_solver.py examples/tooBigFor32.png tooBigFor32.png +./resistor_solver.py examples/wideStripe.png wideStripe.png +./resistor_solver.py examples/wideStripe_punched.png wideStripe_punched.png diff --git a/resistor_solver.py b/resistor_solver.py index af87228..8529da9 100755 --- a/resistor_solver.py +++ b/resistor_solver.py @@ -4,6 +4,8 @@ import PIL.Image import numpy +import scipy.sparse +import scipy.sparse.linalg import sys PIL.Image.warnings.simplefilter('ignore', PIL.Image.DecompressionBombWarning) @@ -26,9 +28,20 @@ image = numpy.array(image_pil) #print('shape', image.shape) #print('dtype', image.dtype) assert len(image.shape) == 2 and image.dtype == numpy.uint8 -assert numpy.all(image < 4) # colours are 0 = black, 1 = blue, 2 = red, 3 = white -#print('xxx', image_pil.palette.tobytes()[:12]) +palette = numpy.array(list(image_pil.palette.tobytes()), numpy.uint8) +#print('palette', palette) +assert numpy.all( + (palette >= 0x80) == numpy.array( + [ + False, False, False, + False, False, True, + True, False, False, + True, True, True, + ], + bool + ) +) ys, xs = image.shape n = ys * xs @@ -42,25 +55,32 @@ image_vert[:-1, :] = numpy.logical_and(image_nz[:-1, :], image_nz[1:, :]) # KCL is enforced as follows: # A V = I where V = voltage at node, I = net current out of node -# I is current "unaccounted for", i.e. current that cancels R currents +# (when node is electrode, positive I means current is entering the array) # resistor R connected n1 -> n2: -# causes a current of (V(n2) - V(n1)) / R, positive when V(n2) > V(n1) -# => when current is positive, it should decrease I(n1) and increase I(n2) -# => I(n1) -= 1/R V(n2) - 1/R V(n1), I(n2) += 1/R V(n2) - 1/R V(n1) -# => I(n1) += 1/R V(n1) - 1/R V(n1), I(n2) += -1/R V(n1) + 1/R V(n2) -A = numpy.zeros((n, n), numpy.int8) +# causes a current of (V(n1) - V(n2)) / R, positive when V(n1) > V(n2) +# => when current is positive, it should increase I(n1) and decrease I(n2) +# => I(n1) += 1/R V(n1) - 1/R V(n2), I(n2) -= 1/R V(n1) - 1/R V(n2) +v = [] +i = [] +j = [] for n1 in numpy.nonzero(image_horiz.reshape((n,)))[0]: n2 = n1 + 1 - A[n1, n1] += 1 - A[n1, n2] -= 1 - A[n2, n1] -= 1 - A[n2, n2] += 1 + v.extend([1, -1, -1, 1]) + i.extend([n1, n1, n2, n2]) + j.extend([n1, n2, n1, n2]) for n1 in numpy.nonzero(image_vert.reshape((n,)))[0]: n2 = n1 + ys - A[n1, n1] += 1 - A[n1, n2] -= 1 - A[n2, n1] -= 1 - A[n2, n2] += 1 + v.extend([1, -1, -1, 1]) + i.extend([n1, n1, n2, n2]) + j.extend([n1, n2, n1, n2]) +v = numpy.array(v, numpy.int32) +i = numpy.array(i, numpy.int32) +j = numpy.array(j, numpy.int32) +A = scipy.sparse.coo_array( + (v, (i, j)), + shape = (n, n), + dtype = numpy.int32 +).tocsr() # partition nodes into 3 groups: # 0: black + blue (electrode), 1: red (electrode), 2: white (conductor) @@ -93,7 +113,7 @@ A22 = A[g2, :][:, g2] A11_V1 = numpy.sum(A11.astype(numpy.int32), 1) A21_V1 = numpy.sum(A21.astype(numpy.int32), 1) print('solve') -V2 = numpy.linalg.solve( +V2 = scipy.sparse.linalg.spsolve( A22.astype(numpy.double), -A21_V1.astype(numpy.double) ) diff --git a/stillOKfor32.png b/stillOKfor32.png deleted file mode 100644 index 4b51a32..0000000 Binary files a/stillOKfor32.png and /dev/null differ