The Cube Problem

In this example we wish to take a look at a simple problem in order to demonstrate some of Kirchhoff’s abilities. The problem involves a cube, where each one of the 12 edges is a pipe with resistance 1, and we wish to find the equivalent resistance of the entire cube between two opposing vertices.

There are no nuclear components involved in this question. The graph includes only two parts:

  1. A Pump

  2. A cube of 12 pipes, acting as resistors.

We will solve the problem here numerically with Kirchhoff. It is not hard to solve by hand and discover the equivalent resistance of the cube is 5/6 of the resistance of each pipe (so the flow is 6/5 and their product is the pressure difference).

Therefore, we will use \(\Delta p = 5\), which means the total flow should amount to 6.

The cube is described by the following image, where the pump generates a potential difference on an additional pipe from node H to node A:

[1]:
import numpy as np

from stream.calculations import Pump, Resistor
from stream.calculations.kirchhoff import Junction
from stream.composition import FlowGraph, flow_edge

Components

Pump

[2]:
dp0 = 5
pump = Pump(pressure=dp0, name="Pump")

Junctions

We define each vertex of the cube as a Junction which is necessary as multiple entries are involved.

[3]:
A = Junction("A")
B = Junction("B")
C = Junction("C")
D = Junction("D")
E = Junction("E")
F = Junction("F")
G = Junction("G")
H = Junction("H")

We also need to define the 12 different resistors, as each edge is a distinct object with identical properties. This is done directly at the subsequent flow_graph

Assembling a Simulation

We create the graph that represents the cube:

[4]:
fg = FlowGraph(
    flow_edge((A, B), Resistor(1, "AB")),
    flow_edge((A, C), Resistor(1, "AC")),
    flow_edge((A, E), Resistor(1, "AE")),
    flow_edge((B, D), Resistor(1, "BD")),
    flow_edge((B, F), Resistor(1, "BF")),
    flow_edge((C, D), Resistor(1, "CD")),
    flow_edge((C, G), Resistor(1, "CG")),
    flow_edge((D, H), Resistor(1, "DH")),
    flow_edge((E, F), Resistor(1, "EF")),
    flow_edge((E, G), Resistor(1, "EG")),
    flow_edge((F, H), Resistor(1, "FH")),
    flow_edge((G, H), Resistor(1, "GH")),
    flow_edge((H, A), pump),
)

The solution

Now we can solve the problem. We will use a vector of 1’s as the initial guess for the solver.

[5]:
agr = fg.aggregator
steady = agr.save(agr.solve_steady(np.ones(len(agr))))

The total flow from H back to A:

[6]:
steady["Kirchhoff"]["(H -> A, 0)"]
[6]:
np.float64(6.0)

Just like we calculated!

We can also look at the flow in different pipes inside the cube:

From symmetry, the flow should be equal for the three pipes leaving the entry node (A), or the three pipes entering the exit node (H), so 1/3 for each. For the rest, the flow should be 1/6. Let’s check if it is indeed so:

[7]:
total_flow = steady["Kirchhoff"]["(H -> A, 0)"]
print(f"Exiting A: {steady['Kirchhoff']['(A -> B, 0)']:.2f}")
print(f"Entering H: {steady['Kirchhoff']['(F -> H, 0)']:.2f}")
print(f"A middle pipe: {steady['Kirchhoff']['(E -> G, 0)']:.2f}")
Exiting A: 2.00
Entering H: 2.00
A middle pipe: 1.00

Again, just like we calculated.

The entire hydarulic solution is summed up nicely here:

[8]:
df = steady.to_dataframe()
df[df.variable != "Tin"].reset_index(drop=True)
[8]:
calculation variable i j value
0 AB pressure 0 0 -2.0
1 AC pressure 0 0 -2.0
2 AE pressure 0 0 -2.0
3 BD pressure 0 0 -1.0
4 BF pressure 0 0 -1.0
5 CD pressure 0 0 -1.0
6 CG pressure 0 0 -1.0
7 EF pressure 0 0 -1.0
8 EG pressure 0 0 -1.0
9 DH pressure 0 0 -2.0
10 FH pressure 0 0 -2.0
11 GH pressure 0 0 -2.0
12 Pump pressure 0 0 5.0
13 Kirchhoff (A -> B, 0) 0 0 2.0
14 Kirchhoff (A -> C, 0) 0 0 2.0
15 Kirchhoff (A -> E, 0) 0 0 2.0
16 Kirchhoff (B -> D, 0) 0 0 1.0
17 Kirchhoff (B -> F, 0) 0 0 1.0
18 Kirchhoff (C -> D, 0) 0 0 1.0
19 Kirchhoff (C -> G, 0) 0 0 1.0
20 Kirchhoff (E -> F, 0) 0 0 1.0
21 Kirchhoff (E -> G, 0) 0 0 1.0
22 Kirchhoff (D -> H, 0) 0 0 2.0
23 Kirchhoff (F -> H, 0) 0 0 2.0
24 Kirchhoff (G -> H, 0) 0 0 2.0
25 Kirchhoff (H -> A, 0) 0 0 6.0