The TPLS is an physical simulator runing on top of Erlang. It is based on discretizing the heat equation:
The TPLS uses a lattice of erlang processes (shortly: nodes) which exchange messages. All nodes are supervized by "Big Brother" who prevents premature crashes.
This is how the TPLS operates. In the blueprint every node is represented by a circle. The lines are logical connections. This is how the lattice looks like:
Every node knows its temperature and neighbors:
For time evolution, the node has to request the temperatures of its neighbors, the thermal diffusivity and the basis of the system which are stored in the state of the supervisor and calcutate the next temperature via the discrete heat equation:
Here
Where
Note:
This is not a generalized formula for the Laplacian. For the general case let
$n \left(\partial T \right)$ be the number of neighbors. Then the general Laplacian is:
$$ \nabla^2 T = \frac{1}{\Delta x^2} \left( \sum{\partial T} - n \left( \partial T \right) T \right) $$ This is the actual forumla used in the TPLS.
To calculate every node's new temperature we have to traverse the lattice. The algorithm for this looks like this scheme:
Now let's talk about the supervisor: The Big Brother. He looks after all processes in the lattice. When a process exits Big Brother has to replace it. The temperature of the new process is the average of its neighours.
The thermal diffusivity coefficient is stored in Big Brother. For time evolution every process has to request the coefficient for Big Brother.
Here is a table of the used materials in the TPLS and their coefficient:
Material | Thermal Diffusivity |
---|---|
carbon | 216.6 |
silver | 165.63 |
gold | 127 |
copper | 111 |
aluminium | 97 |
silicon | 88 |
tin | 40 |
iron | 23 |
glass | 0.34 |
brick | 0.27 |
rubber | 0.11 |
Note:
The TPLS uses units of
$mm^2/s$ for thermal diffusivity.
The TPLS is build for Linux. It can be used on other OS, but you have to configure it manualy. Firstly, pull the source code. Then run the compiler.sh
script:
chmod +x ./compiler.sh
./compiler.sh
This script compiles every erlang module in the repository. Now, you can open the erlang shell with the erl
command and use the node
, bigbrother
and therm
modules.
Let's build a simulation. Firstly, we will initialize an "empty" bigbrother
process:
BB = bigbrother:start().
By default the material of the system is set to iron. You can change it by passing the name of the material as an argument to the bigbrother:start/1
function:
Material = gold,
BB = bigbrother:start(Material).
For simplisity we will simulate how the temperature of a beam evolves. Let's create a 1D basis. It will begin at
Start = -1, % mm
End = 1, % mm
DX = 0.1, % mm
X = therm:base(Start, DX, End).
Note:
The TPLS uses 1 mm as 1 unit length and 1 s for 1 unit time. For temperature the TPLS uses Kelvin. This means that the basis
X
starts from -1 mm and ends in 1 mm. The distance between the nodes is 0.1 mm.Also I will comment the units of a variable when it is initialized if you haven't read the note just in case.
Let's use therm:beam/2
function:
F = fun
(X) -> 20 * math:exp( - X * X ) + 300
end,
T = therm:beam(F, X). %% K
Now let's create the processes. We will message the bigbrother
process as developers. We will tell Big Brother to create a beam with temperatures T
:
BB ! { dev, { start, { beam, T } } }.
Then we will tell him that we have used X
as a basis:
BB ! { dev, { set, { base, X } } }.
Now we are ready to simulate how the temperatures of the beam will evolve. Simply message the supervisor like this:
DT = 0.01, %% s
BB ! { dev, { evolve, DT } }.
This will evolve the state with
Note:
Do not use big values for
$\Delta t$ . It will break the simulation. Try to use as small as possible value for$\Delta t$ . Do not use zero or negative numbers. I case you want more formal warning:
$$ 1 \gg \Delta t > 0 $$
Unfortunately this is a very slow time evolution. Let's speed things up. We will still use
To see how many times we have to do the simulation we will divide the total time by the time interval of one simulation:
For our case that is
TotalTime = 1, %% s
N = TotalTime / DT,
BB ! { dev, { nevolve, N, DT } }.
Good. You did it! This wasn't hard was it?
How about a 2D simulation? 2D is the same as 1D except we have to include one more base. Let's see how to code this. Let's create two basis:
X = therm:base(-1, 0.1, 1),
Y = therm:base(-2, 0.1, -2).
Here our X axis will start at
Note:
Both basis must have the same distanse between nodes:
$$ \Delta x = \Delta y $$
Now let's create a mesh basis. We will simply use the therm:mesh/2
function. This will create a 2D list of all positions:
Mesh = therm:mesh(X, Y).
Note:
You can use the
therm:square/1
function forX = Y
cases. These lines of code are equivalent:Mesh = therm:mesh(X, X).Mesh = therm:square(X).
In 2D our thermal function will look like this:
F = fun
({ X, Y }) -> 20 * math:exp( - X * X - Y * Y ) + 300
end.
Let's apply this to our mesh using the therm:sheet/2
function:
T = therm:sheet(F, Mesh).
We are almost done. Let's send the temperatures and mesh to the Big Brother:
BB ! { dev, { start, { sheet, T } } },
BB ! { dev, { set, { mesh, Mesh } } }.
And we are done. The time evolution is the same as 1D so you know the drill.