import React, { useState, useMemo } from 'react'; // Iconos en línea nativos (no requieren instalación) const IconWind = () => ; const IconAperture = () => ; const IconActivity = () => ; const IconDatabase = () => ; const IconExternalLink = () => ; // Helpers para dibujar gráficos vectoriales puros const mapVal = (val, inMin, inMax, outMin, outMax) => ((val - inMin) / (inMax - inMin)) * (outMax - outMin) + outMin; export default function DDISDashboard() { const [coupling, setCoupling] = useState(80000); const [etaEff, setEtaEff] = useState(1.2); const [f0, setF0] = useState(1200); const [qFactor, setQFactor] = useState(15); const [targetV, setTargetV] = useState(0.3); const [ehtTarget, setEhtTarget] = useState('SgrA'); const [binaryMass, setBinaryMass] = useState(65); const baseShadowUas = ehtTarget === 'SgrA' ? 51.8 : 39.0; const r_345_uas = baseShadowUas * (1 + 0.5 * coupling / Math.pow(345, 2)); const r_230_uas = baseShadowUas * (1 + 0.5 * coupling / Math.pow(230, 2)); const absoluteShiftUas = (r_230_uas - r_345_uas).toFixed(2); const ligoData = useMemo(() => { const data = []; const t_merger = 0; const t_offset = -0.0035; const tau = qFactor / (Math.sqrt(2) * Math.PI * f0); const A_burst = 3.5 * Math.sqrt(etaEff); const freqScale = 65 / binaryMass; for (let t = -0.04; t <= 0.01; t += 0.0002) { let h_gr = 0; if (t < t_merger) { const tau_t = t_merger - t; const f_gr = 40 * freqScale * Math.pow(tau_t + 0.005, -3/8); const phase = 2 * Math.PI * f_gr * t; h_gr = 2 * Math.pow(tau_t + 0.005, -1/4) * Math.cos(phase); } else { h_gr = 2 * Math.pow(0.005, -1/4) * Math.exp(-t/0.003) * Math.cos(2 * Math.PI * 200 * freqScale * t); } const env = Math.exp(-Math.pow(t - t_offset, 2) / Math.pow(tau, 2)); const osc = Math.cos(2 * Math.PI * f0 * (t - t_offset)); data.push({ tNum: parseFloat(t.toFixed(4)), GR: h_gr, sGB: h_gr + (A_burst * env * osc) }); } return data; }, [etaEff, f0, qFactor, binaryMass]); const quasarData = useMemo(() => { const data = []; for (let x = 0; x <= 0.2; x += 0.005) { data.push({ ratio: x, velocity: Math.sqrt(1 - Math.pow(1 + x, -2)) }); } return data; }, []); const requiredRatio = (Math.sqrt(1 / (1 - Math.pow(targetV, 2))) - 1); // Lógica de Renderizado SVG para Cuásar const qXMin = 0, qXMax = 0.2, qYMin = 0, qYMax = 0.6; const qPts = quasarData.map(d => `${mapVal(d.ratio, qXMin, qXMax, 40, 380)},${mapVal(d.velocity, qYMin, qYMax, 160, 20)}`).join(' L '); const reqX = mapVal(requiredRatio, qXMin, qXMax, 40, 380); const reqY = mapVal(targetV, qYMin, qYMax, 160, 20); // Lógica de Renderizado SVG para LIGO const lXMin = -0.04, lXMax = 0.01; let lYMax = 0; ligoData.forEach(d => { if (Math.abs(d.sGB) > lYMax) lYMax = Math.abs(d.sGB); if (Math.abs(d.GR) > lYMax) lYMax = Math.abs(d.GR); }); lYMax = Math.ceil(lYMax) || 1; const lYMin = -lYMax; const grPts = ligoData.map(d => `${mapVal(d.tNum, lXMin, lXMax, 40, 380)},${mapVal(d.GR, lYMin, lYMax, 160, 20)}`).join(' L '); const sgbPts = ligoData.map(d => `${mapVal(d.tNum, lXMin, lXMax, 40, 380)},${mapVal(d.sGB, lYMin, lYMax, 160, 20)}`).join(' L '); const refX = mapVal(-0.0035, lXMin, lXMax, 40, 380); return (
Plataforma de validación sGB para colaboraciones LIGO/EHT
Acceda al laboratorio de computación técnica para cargar archivos CSV propios y validar el modelo contra datos reales de observatorios.