Scan to open on your phone
Point a camera at the QR code - it opens this exact paste, no app needed.
https://codepastes.com/zzgt1kyhq26pzhbdsin-tituloPlain Text
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simulador Interactivo de Espines y Campo Magnético</title>
<style>
:root {
--bg-color: #0f172a;
--panel-color: #1e293b;
--text-color: #f8fafc;
--accent-up: #ef4444;
--accent-down: #3b82f6;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: var(--bg-color);
color: var(--text-color);
margin: 0;
padding: 20px;
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
}
h1 {
margin-bottom: 10px;
font-size: 1.8rem;
text-align: center;
}
.container {
display: flex;
flex-wrap: wrap;
gap: 20px;
justify-content: center;
max-width: 1000px;
width: 100%;
}
.panel {
background-color: var(--panel-color);
border-radius: 12px;
padding: 20px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.controls {
flex: 1;
min-width: 280px;
display: flex;
flex-direction: column;
gap: 15px;
}
.visualization {
display: flex;
flex-direction: column;
align-items: center;
}
canvas {
background-color: #020617;
border-radius: 8px;
box-shadow: inset 0 2px 4px rgba(0,0,0,0.6);
}
.control-group {
display: flex;
flex-direction: column;
gap: 5px;
}
label {
font-size: 0.9rem;
font-weight: 600;
display: flex;
justify-content: space-between;
}
input[type="range"] {
width: 100%;
accent-color: #10b981;
}
.btn {
background-color: #10b981;
color: white;
border: none;
padding: 10px;
border-radius: 6px;
cursor: pointer;
font-weight: bold;
transition: background 0.2s;
}
.btn:hover {
background-color: #059669;
}
.stats {
margin-top: 10px;
font-family: monospace;
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
font-size: 0.9rem;
}
.stat-box {
background: #0f172a;
padding: 8px;
border-radius: 6px;
text-align: center;
}
</style>
</head>
<body>
<h1>Simulación Cuántica: Espines en un Campo Magnético (<span style="color:var(--accent-up)">B</span>)</h1>
<div class="container">
<!-- Panel de Control -->
<div class="panel controls">
<div class="control-group">
<label for="magneticField">
Campo Magnético Externo (B): <span id="bVal">0.0</span>
</label>
<input type="range" id="magneticField" min="-2" max="2" step="0.1" value="0">
<small style="color:#94a3b8">Valores > 0 fuerzan alineación Hacia Arriba (Rojo). Valores < 0 hacia Abajo (Azul).</small>
</div>
<div class="control-group">
<label for="temperature">
Temperatura (Agitación Térmica): <span id="tVal">1.5</span>
</label>
<input type="range" id="temperature" min="0.1" max="5" step="0.1" value="1.5">
<small style="color:#94a3b8">La temperatura alta destruye el orden magnético creando caos.</small>
</div>
<button class="btn" id="btnReset">Aleatorizar Espines</button>
<button class="btn" id="btnAlign" style="background-color:#6366f1">Alinear con el Campo</button>
<div class="stats">
<div class="stat-box">Magnetización Neto:<br><span id="netMag" style="font-weight:bold; font-size:1.2rem;">0%</span></div>
<div class="stat-box">Energía del Sistema:<br><span id="sysEnergy" style="font-weight:bold; font-size:1.2rem;">0</span></div>
</div>
</div>
<!-- Panel de Visualización -->
<div class="panel visualization">
<canvas id="spinCanvas" width="400" height="400"></canvas>
</div>
</div>
<script>
const canvas = document.getElementById('spinCanvas');
const ctx = canvas.getContext('2d');
// Parámetros de la simulación
const GRID_SIZE = 40; // Matriz de 40x40 espines
const CELL_SIZE = canvas.width / GRID_SIZE;
let grid = [];
// Parámetros físicos dinámicos
let B = 0.0; // Campo magnético externo
let T = 1.5; // Temperatura
const J = 1.0; // Constante de acoplamiento entre espines vecinos (Ferromagnetismo)
// Inicializar la red de espines de manera aleatoria (+1 o -1)
function initGrid(random = true) {
grid = [];
for (let i = 0; i < GRID_SIZE; i++) {
grid[i] = [];
for (let j = 0; j < GRID_SIZE; j++) {
grid[i][j] = random ? (Math.random() > 0.5 ? 1 : -1) : 1;
}
}
}
// Algoritmo de Metrópolis (Monte Carlo) para simular la física estadística
function updatePhysics() {
for (let step = 0; step < GRID_SIZE * GRID_SIZE; step++) {
// Seleccionar un espín al azar
const x = Math.floor(Math.random() * GRID_SIZE);
const y = Math.floor(Math.random() * GRID_SIZE);
const spin = grid[x][y];
// Condición de frontera periódica (el borde derecho conecta con el izquierdo, etc.)
const left = grid[(x - 1 + GRID_SIZE) % GRID_SIZE][y];
const right = grid[(x + 1) % GRID_SIZE][y];
const up = grid[x][(y - 1 + GRID_SIZE) % GRID_SIZE];
const down = grid[x][(y + 1) % GRID_SIZE];
// Cálculo de la energía local del espín actual
// E = -J * spin * (suma_vecinos) - B * spin
const energyCurrent = -J * spin * (left + right + up + down) - B * spin;
const energyFlipped = -J * (-spin) * (left + right + up + down) - B * (-spin);
const deltaE = energyFlipped - energyCurrent;
// Criterio cuántico/térmico de aceptación de Metrópolis
if (deltaE <= 0 || Math.random() < Math.exp(-deltaE / T)) {
grid[x][y] = -spin; // Cambia el estado del espín
}
}
}
// Renderizar los espines en el Canvas mediante flechas de color
function drawGrid() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
const spin = grid[i][j];
const x = i * CELL_SIZE + CELL_SIZE / 2;
const y = j * CELL_SIZE + CELL_SIZE / 2;
ctx.save();
ctx.translate(x, y);
// Configurar color según la orientación
if (spin === 1) {
ctx.strokeStyle = '#ef4444'; // Rojo = Spin Arriba
ctx.fillStyle = '#ef4444';
} else {
ctx.strokeStyle = '#3b82f6'; // Azul = Spin Abajo
ctx.fillStyle = '#3b82f6';
ctx.rotate(Math.PI); // Voltear flecha hacia abajo
}
// Dibujar una flecha simplificada que representa el vector del Espín
ctx.beginPath();
ctx.moveTo(0, CELL_SIZE/2 - 1);
ctx.lineTo(0, -CELL_SIZE/2 + 1);
ctx.lineWidth = 2;
ctx.stroke();
// Punta de la flecha
ctx.beginPath();
ctx.moveTo(0, -CELL_SIZE/2 + 1);
ctx.lineTo(-2, -CELL_SIZE/4);
ctx.lineTo(2, -CELL_SIZE/4);
ctx.fill();
ctx.restore();
}
}
}
// Calcular datos estadísticos en tiempo real
function updateStats() {
let totalSpin = 0;
let totalEnergy = 0;
for (let i = 0; i < GRID_SIZE; i++) {
for (let j = 0; j < GRID_SIZE; j++) {
const spin = grid[i][j];
totalSpin += spin;
const right = grid[(i + 1) % GRID_SIZE][j];
const down = grid[i][(j + 1) % GRID_SIZE];
totalEnergy += -J * spin * (right + down) - B * spin;
}
}
const totalElements = GRID_SIZE * GRID_SIZE;
const magnetization = (totalSpin / totalElements) * 100;
document.getElementById('netMag').innerText = `${magnetization.toFixed(1)}%`;
document.getElementById('sysEnergy').innerText = totalEnergy.toFixed(0);
// Cambiar color del texto según la dirección de la magnetización neta
const magText = document.getElementById('netMag');
9,928 chars · codepastes.com