Public
Edited
May 14, 2024
Paused
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marginLeft: 60,
grid: true,
color: {
type: "linear",
domain: [-1, 1],
scheme: "turbo",
legend: true// use the "accent" scheme
},
marginRight: 80,
x: {
insetLeft: 0,
label: "Iterations →"
},
y: {
label: "↑ Magnetization",
insetBottom: 0,
tickFormat: ""
},
marks: [
//Plot.axisFy([curMaxValue, curMinValue]),
Plot.ruleY([curMinValue - Math.abs(curMinValue) / 10]),
Plot.ruleX([-stats.length / 25]),
Plot.lineY(statsTemps.filter(s => s.type == "magnetization"), { x: i => i.iter*nIter, y: "value", fy: "T", stroke: s => s.H}),
]
})
Insert cell
stats.slice(-1)
Insert cell
{
if (U.length == 0) {
U[0] = {value: randomLattice == "all down" ? -1*calcEnergy():calcEnergy(), type: "energy", iter: 0, T: T, H: H};
M[0] = {value: calcMagnetization(), type: "magnetization", iter: 0, T: T, H: H, magnetization: externalField};
mutable stats.push(U[0]);
mutable stats.push(M[0]);
}
while (pause) {
const startTime = new Date();
const counter = U.length - 1;
U[counter + 1] = {
value: U[counter].value + isingNIter(nIter),
type: "energy",
iter: counter + 1,
T: T,
H: H
};
M[counter + 1] = {
value: calcMagnetization(),
type: "magnetization",
iter: counter + 1,
T: T,
H: H,
magnetization: externalField,
};
mutable stats.push(U[counter +1]);
mutable stats.push(M[counter +1]);
mutable stats = stats;
mutable statsTemps.push(U[counter +1])
mutable statsTemps.push(M[counter +1])
mutable statsTemps = statsTemps;
//runtimes.push({iterations: nIter, time: new Date()-startTime, gridSize: N})
yield Promises.delay(5, stats)
}
}
Insert cell
isingNIter = (nIter) => {
const dE = []
for (let iter = 0; iter < nIter; iter++) {
const randRow = Math.floor(Math.random() * N);
const randCol = Math.floor(Math.random() * N);
dE.push(deltaEnergy(randRow, randCol))
}
return d3.sum(dE)
}
Insert cell
deltaEnergy = (row, col) => {
let externalEnergy = 0;
if (externalField) externalEnergy = mu*H*grid[row][col];
const dE = (2 * grid[row][col] * (grid[(row + 1 + N) % N][col] + grid[row][(col + 1 + N) % N] +
grid[(row - 1 + N) % N][col] + grid[row][(col - 1 + N) % N]) - externalEnergy);
if (dE < 0 || Math.random() < Math.exp(-dE / T)) {
grid[row][col] *= -1;
return dE
}
return 0
}
Insert cell
calcEnergy = () => {
let energy = 0;
for (let row = 0; row < N; row++) {
for (let col = 0; col < N; col++) {
let externalEnergy = 0
if (externalField) externalEnergy = mu*H*grid[row][col];
energy += (grid[row][col] * (grid[(row + 1 + N) % N][col] + grid[row][(col + 1 + N) % N] +
grid[(row - 1 + N) % N][col] + grid[row][(col - 1 + N) % N]) - externalEnergy)
}
}
return energy
}
Insert cell
calcMagnetization = () => {
return d3.sum(grid.map(row => d3.sum(row)))
}
Insert cell
curMinValue = d3.min(stats.map((u) => u.U))
Insert cell
curMaxValue = d3.max(stats.map((u) => u.U))
Insert cell
mutable stats = {
randomLattice;
reset;
T;
N;
return [];
}
Insert cell
mutable U = {
randomLattice;
reset;
T;
N;
return [];
}
Insert cell
mutable M = {
randomLattice;
reset;
T;
N;
return [];
}
Insert cell
mutable grid = {
reset;
T;
N;
if (randomLattice == "random") return Array.from({length: N}, () => Array.from({length: N}, () => Math.random() < 0.5 ? -1 : 1))
else if (randomLattice == "all up") return Array.from({length: N}, () => Array.from({length: N}, () => 1))
else if (randomLattice == "all down") return Array.from({length: N}, () => Array.from({length: N}, () => -1))
}
Insert cell
mutable statsTemps = [];
Insert cell
magTempData = {
const magData = statsTemps.filter(t => t.type == "magnetization" && !t.magnetization);
const engData = statsTemps.filter(t => t.type == "energy" && !t.magnetization);
const temps = [];
magData.forEach(m => temps.includes(m.T) ? null:temps.push(m.T));
return temps.reduce((arr, T) => {
const magDataForTemp = magData.filter(M => M.T == T);
const engDataForTemp = engData.filter(E => E.T == T);
const meanM = d3.mean(magDataForTemp.slice(-10).map(M => Math.abs(M.value)));
const meanE = d3.mean(engDataForTemp.slice(-10).map(E => E.value));
const varianceM = d3.variance(magDataForTemp.slice(-10).map(M => Math.abs(M.value)));
const varianceE = d3.variance(engDataForTemp.slice(-10).map(E => E.value));
return arr.concat([{
T: T,
mean: meanM,
variance: varianceM,
type: "magnetization"
}, {
T: T,
mean: meanE,
variance: varianceE,
type: "energy",
}])
}, []);
}
Insert cell
mu = 1
Insert cell
nIter = 5000;
Insert cell
pause = paused == "playing" ? true:false
Insert cell
Insert cell
import { ButtonToggle } from "@harrystevens/toggle-button-text"
Insert cell
import { style as faStyle, fas } from "@airbornemint/fontawesome"
Insert cell
faStyle({solid: true})
Insert cell
/*{
const height = 450
const context = DOM.context2d(width, height);

const margin = 50;
const maxPoints = 900;

context.clearRect(0, 0, width, height);

const offsetY = 100;
const offsetX = 200;

const drawCoordinateSystem = () => {
context.strokeStyle = "#000000";
context.lineWidth = 2;
context.beginPath();
context.moveTo(margin+30, height-margin+25);
context.lineTo(margin+30, margin); // Y-axis
context.moveTo(margin-25, height - margin);
context.lineTo(width - margin, height - margin); // X-axis
context.stroke();
// Draw arrow heads
context.beginPath();
context.moveTo(width - margin, height - margin);
context.lineTo(width - margin - 10, height - margin - 5);
context.moveTo(width - margin, height - margin);
context.lineTo(width - margin - 10, height - margin + 5);
context.moveTo(margin+30, margin);
context.lineTo(margin - 5 +30, margin + 10);
context.moveTo(margin + 30, margin);
context.lineTo(margin + 5 + 30, margin + 10);
context.stroke();

context.strokeStyle = "#000000";
// upper left tick
context.beginPath();
context.moveTo(margin-5 +30, margin+20);
context.lineTo(margin+5 + 30, margin+20);
// lower left tick
context.moveTo(margin-5 +30, height-offsetY);
context.lineTo(margin+5 +30, height-offsetY);
// lower left X
context.moveTo(offsetX/3+margin, height-margin-5);
context.lineTo(offsetX/3+margin, height-margin+5);
// lower right X
context.moveTo(width - offsetX + margin, height-margin-5);
context.lineTo(width - offsetX + margin, height-margin+5);
context.stroke();

// Adding tick labels
//context.fillStyle = "#000000";
// context.fillText(tickValueX.toFixed(1), margin + i*(width - 2 * margin)/numberOfTicks, height - margin + tickSize);
// context.fillText(tickValueY.toFixed(1), margin - tickSize, height - margin - i*(height - 2 * margin)/numberOfTicks);
// context.fill();

context.font = "16px Arial";
context.fillText("Energy", margin, margin - 10);
context.fillText("0", offsetX/3+margin-4, height - margin + 20);
context.fillText("", width - offsetX, height - margin + 20);
context.fillText("Iterations", width - 100, height - margin - 20);
return context
}
drawCoordinateSystem();

//U[0] = {U: calcEnergy(), iter: 0};

const updateGraph = () => {
const maxX = d3.max(U.map(d => d.iter));
const maxY = d3.max(U.map(d => d.U));
const minY = d3.min(U.map(d => d.U));

const energyScaling = (height - margin - 100)

const xScaling = (width - margin - offsetX) / maxX;
const yScaling = (height-margin-offsetY-20)/(maxY-minY);
// Dynamically adjust the iteration step to maintain performance
const iterationStep = Math.max(1, Math.floor(U.length / maxPoints));
context.beginPath();
for (let i = 0; i < U.length; i += iterationStep) {
const x = margin + U[i].iter * xScaling + offsetX/3;
//const y = (maxY-U[i].U) *yScaling + maxY-minY;
const y = yScaling * (maxY - U[i].U) + offsetY/2+20
context.lineTo(x, y);
}
context.stroke();
// Draw points
// for (let i = 100; i < U.length; i += iterationStep) {
// const x = margin + U[i].iter * xScaling;
// const y = height - margin - U[i].U * yScaling;
// context.beginPath();
//context.arc(x, y, 2, 0, Math.PI * 2);
// context.fill();
// }
// Update dynamic axis labels
context.font = "16px Arial";
context.fillStyle = "#000000";
// Y-axis label (Energy)
context.fillText(`${(maxY).toFixed(0)}`, 0, margin+25);
context.fillText(`${(minY).toFixed(0)}`, 0, height-offsetY+5);
// X-axis label (Iterations)
context.fillText(`${(maxX*10000).toFixed(0)}`, width - offsetX, height - margin + 20);
};


while (false) {
const counter = U.length - 1;
U[counter + 1] = {
U: U[counter].U + isingNIter(10000),
iter: counter + 1
};

context.save();
context.clearRect(0, 0, width, height);
drawCoordinateSystem();
updateGraph();
context.restore();
yield Promises.delay(N/150, context.canvas);
}
}*/
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more