sin-titulo

Pasted Oct 7, 2026, 8:34 PM1 file278 lines

Scan to open on your phone

Point a camera at the QR code - it opens this exact paste, no app needed.

https://codepastes.com/zzgt1kyhq26pzhbd
sin-titulo
<!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