Task: Resistor mesh





Java: import java.util.ArrayList;
import java.util.List;

public class ResistorMesh {
    private static final int S = 10;

    private static class Node {
        double v;
        int fixed;

        Node(double v, int fixed) {
            this.v = v;
            this.fixed = fixed;
        }
    }

    private static void setBoundary(List<List<Node>> m) {
        m.get(1).get(1).v = 1.0;
        m.get(1).get(1).fixed = 1;

        m.get(6).get(7).v = -1.0;
        m.get(6).get(7).fixed = -1;
    }

    private static double calcDiff(List<List<Node>> m, List<List<Node>> d, int w, int h) {
        double total = 0.0;
        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                double v = 0.0;
                int n = 0;
                if (i > 0) {
                    v += m.get(i - 1).get(j).v;
                    n++;
                }
                if (j > 0) {
                    v += m.get(i).get(j - 1).v;
                    n++;
                }
                if (i + 1 < h) {
                    v += m.get(i + 1).get(j).v;
                    n++;
                }
                if (j + 1 < w) {
                    v += m.get(i).get(j + 1).v;
                    n++;
                }
                v = m.get(i).get(j).v - v / n;
                d.get(i).get(j).v = v;
                if (m.get(i).get(j).fixed == 0) {
                    total += v * v;
                }
            }
        }
        return total;
    }

    private static double iter(List<List<Node>> m, int w, int h) {
        List<List<Node>> d = new ArrayList<>(h);
        for (int i = 0; i < h; ++i) {
            List<Node> t = new ArrayList<>(w);
            for (int j = 0; j < w; ++j) {
                t.add(new Node(0.0, 0));
            }
            d.add(t);
        }

        double[] cur = new double[3];
        double diff = 1e10;

        while (diff > 1e-24) {
            setBoundary(m);
            diff = calcDiff(m, d, w, h);
            for (int i = 0; i < h; ++i) {
                for (int j = 0; j < w; ++j) {
                    m.get(i).get(j).v -= d.get(i).get(j).v;
                }
            }
        }

        for (int i = 0; i < h; ++i) {
            for (int j = 0; j < w; ++j) {
                int k = 0;
                if (i != 0) k++;
                if (j != 0) k++;
                if (i < h - 1) k++;
                if (j < w - 1) k++;
                cur[m.get(i).get(j).fixed + 1] += d.get(i).get(j).v * k;
            }
        }

        return (cur[2] - cur[0]) / 2.0;
    }

    public static void main(String[] args) {
        List<List<Node>> mesh = new ArrayList<>(S);
        for (int i = 0; i < S; ++i) {
            List<Node> t = new ArrayList<>(S);
            for (int j = 0; j < S; ++j) {
                t.add(new Node(0.0, 0));
            }
            mesh.add(t);
        }

        double r = 2.0 / iter(mesh, S, S);
        System.out.printf("R = %.15f", r);
    }
}







Ada: with Ada.Text_IO; use Ada.Text_IO;
procedure ResistMesh is
   H, W : constant Positive := 10;
   rowA, colA : constant Positive := 2; 
   rowB : constant Positive := 7;
   colB : constant Positive := 8;

   type Ntype is (A, B, Free);
   type Vtype is digits 15;
   type Node is record
      volt : Vtype := 0.0;
      name : Ntype := Free;
   end record;
   type NodeMesh is array (Positive range <>, Positive range <>) of Node;
   package IIO is new Ada.Text_IO.Float_IO (Vtype);
   mesh, dmesh : NodeMesh (1 .. H, 1 .. W);
   curA, curB, diff : Vtype;

   procedure set_AB (mesh : in out NodeMesh) is begin
      mesh (rowA, colA).volt :=  1.0;  mesh (rowA, colA).name := A;
      mesh (rowB, colB).volt := -1.0;  mesh (rowB, colB).name := B;
   end set_AB;

   function sides (i : Positive; j : Positive) return Vtype is
      s : Integer := 0;
   begin
      if i /= 1 and i /= H then s := s + 2; else s := s + 1; end if;
      if j /= 1 and j /= W then s := s + 2; else s := s + 1; end if;
      return Vtype (s);
   end sides;

   procedure calc_diff (mesh : NodeMesh; dmesh : out NodeMesh;
      total : out Vtype)  is
      n : Natural;
      v : Vtype := 0.0;
   begin
      total := 0.0;
      for i in Positive range 1 .. H loop
         for j in Positive range 1 .. W loop
            n := 0;    v := 0.0;
            if  i /= 1 then v := v + mesh (i - 1, j).volt; n := n + 1; end if;
            if j /= 1 then  v := v + mesh (i, j - 1).volt; n := n + 1; end if;
            if i < H then v := v + mesh (i + 1, j).volt; n := n + 1; end if;
            if j < W then v := v + mesh (i, j + 1).volt; n := n + 1; end if;
            v := mesh (i, j).volt - v / Vtype (n);
            dmesh (i, j).volt := v;
            if mesh (i, j).name = Free then total := total + v ** 2; end if;
         end loop;
      end loop;
   end calc_diff;

begin

   loop
      set_AB (mesh);
      calc_diff (mesh, dmesh, diff);
      exit when diff < 1.0e-40;
      for i in Positive range 1 .. H loop
         for j in Positive range 1 .. W loop
            mesh (i, j).volt := mesh (i, j).volt - dmesh (i, j).volt;
         end loop;
      end loop;
   end loop;

   curA := dmesh (rowA, colA).volt * sides (rowA, colA);
   curB := dmesh (rowB, colB).volt * sides (rowB, colB);
   diff := 4.0 / (curA - curB);
   IIO.Put (diff, Exp => 0); New_Line;
end ResistMesh;