Una grieta atravesando un cristal

Una grieta no puede correr más deprisa que las ondas que avisan de que está llegando. Ese límite —la velocidad de Rayleigh— sale de las constantes elásticas del material, y en un cristal bidimensional de Lennard-Jones las constantes elásticas se pueden escribir en una línea. Así que aquí no hay nada que ajustar: la referencia es una fórmula cerrada y la simulación tiene que caer donde la teoría dice. Esto es ese cálculo completo.
Lectura rápida
- Qué se simula. Una lámina cristalina de 43.519 átomos (337 × 140 σ) con una entalla
en el borde izquierdo, cargada de golpe en modo I y dejada evolucionar hasta que la
grieta la cruza. Dinámica molecular con LAMMPS,
units lj,dimension 2. - Por qué este sistema. Con el radio de corte entre los primeros y los segundos vecinos, el cristal triangular tiene parámetro de red, constantes elásticas y energía de superficie analíticas exactas. No hay potencial que validar contra tablas: hay fórmulas contra las que comprobar la instalación.
- Antes del resultado, la referencia. Seis magnitudes medidas en LAMMPS y comparadas con su expresión cerrada: todas coinciden a nivel de redondeo ( o mejor). De ellas sale exacto y la velocidad de Rayleigh .
- Qué sale. La grieta recorre 190 σ y se detiene al agotarse la energía almacenada. En el tramo de propagación franca va a 1,443 σ/τ, es decir 0,298 : el valor de libro para fractura frágil (entre 0,2 y 0,5).
- Qué no demuestra. Que la velocidad caiga por debajo de es compatibilidad con un límite, no el acierto de un número predicho. Y el criterio de Griffith aquí solo da el orden de magnitud, porque la teoría continua ignora que la grieta se queda atrapada entre filas de átomos.
- Se puede repetir. Un
run.shque hace la validación, la simulación (unos tres minutos) y las salidas, con LAMMPS sin paquetes especiales.
Nota de notación. En unidades de Lennard-Jones hay dos colisiones de símbolos inevitables: es la energía del potencial y la deformación; es la distancia del potencial y la tensión. Las dos son convenio estándar y no merece la pena inventarse otro, así que aquí la deformación y la tensión van siempre con subíndice y los símbolos sueltos son las unidades.
Por qué se rompen los cristales, y por qué la teoría continua no basta
La mecánica de la fractura clásica responde a cuándo se rompe algo con un balance de energía. Una grieta avanza si al avanzar libera más energía elástica de la que cuesta crear las dos superficies nuevas. Eso es Griffith, y es una idea de 1921 que funciona asombrosamente bien: para una entalla de longitud en el borde de una lámina,
donde es la energía de superficie, el módulo de Young y ese 1,12 el factor geométrico de una grieta que sale del borde en lugar de estar en el interior. Con los números de este cristal —que se validan más abajo— la deformación crítica sale .
El problema de esa fórmula es que no contiene ni un átomo. Trata el sólido como un medio continuo, la grieta como un corte matemático de espesor cero y la superficie como una energía por unidad de longitud. Hay tres cosas que se le escapan, y las tres aparecen en cuanto se miran los átomos:
- La punta no es un punto. La solución elástica da una tensión que diverge como al acercarse a la punta. Eso no puede ser: a un par de distancias interatómicas de la punta la tensión es finita, porque los enlaces se estiran hasta que se rompen y no más. La zona donde la teoría continua deja de valer mide unos pocos nanómetros —en esta simulación, unos pocos σ—, y es justo la zona que decide si la grieta avanza.
- La red atrapa la grieta. Avanzar una fila de átomos cuesta pasar una barrera, igual que mover una dislocación cuesta el Peierls. Griffith dice que por encima de la grieta debe correr; la red dice que hasta cierta sobrecarga la punta se queda enganchada entre dos filas. En esta lámina eso ocurre de verdad: por debajo de —más del doble de la crítica de Griffith— la grieta no arranca, y cuando arranca se para varias veces por el camino. Se ve a simple vista en la gráfica de posición frente a tiempo.
- Hay un techo de velocidad, y no es el del sonido. Una grieta que avanza tiene que mover el campo de tensión que la rodea, y ese campo se reorganiza a la velocidad de las ondas elásticas. La condición de que el balance de energía siga cerrando impone que la punta no supere la velocidad de las ondas de Rayleigh , que son las que viajan por una superficie libre: exactamente la superficie que la grieta va creando. Es un límite teórico limpio, y medirlo es la forma más directa de comprobar que la simulación está haciendo mecánica y no decoración.
Este montaje existe para mirar esas tres cosas con átomos contados, y a la vez para tener una referencia cerrada contra la que medirse. Es la mejor combinación posible para un cálculo de validación: un sistema lo bastante simple como para resolverlo a mano y lo bastante real como para romperse.
El montaje
Una lámina rectangular de red triangular, con una entalla abierta desde el borde izquierdo quitando una fila de átomos, y tracción perpendicular a la grieta (modo I):
| Red | triangular, Lennard-Jones, radio de corte 1,5 σ |
| Geometría | 300 × 72 celdas, 43.519 átomos (≈ 337 × 140 σ) |
| Entalla | fila de átomos eliminada desde el borde izquierdo, 18 % de la longitud (≈ 60 σ) |
| Carga | modo I: deformación aplicada de golpe y de forma afín |
| Contorno | bordes libres salvo 3 filas congeladas arriba y abajo (desplazamiento impuesto) |
| Temperatura | , termostato de Langevin |
| Paso de tiempo | 0,004 τ, hasta t = 240 τ |
| Salidas | 240 volcados con posición y tensión por átomo |
Cuatro decisiones del montaje que no son obvias y que condicionan el resultado:
El radio de corte no es un detalle de eficiencia, es el modelo. En la red triangular relajada los seis primeros vecinos están a 1,122 σ y los segundos a 1,943 σ. Cortar en 1,5 σ deja dentro los primeros y fuera los segundos, y eso convierte el cristal en un problema resoluble: con solo primeros vecinos, el equilibrio exige y todo lo demás sale en cerrado. Con un corte de 2,5 σ —el habitual en Lennard-Jones— el cristal sería más realista y la validación dejaría de ser exacta.
Se carga de golpe y no se sigue cargando. Es el protocolo clásico de fractura en MD: se aplica una deformación afín por encima de la crítica, se congelan las filas de los extremos para mantenerla y se deja correr. La grieta avanza con la energía elástica ya almacenada, que es lo que le da una velocidad estacionaria limpia en lugar de una que crece mientras se tira. El precio es que la energía se agota: por eso la grieta se frena antes de llegar al final de la lámina.
La carga es 4,5 veces la crítica de Griffith. No es generosidad: por debajo de unas dos veces y media la punta se queda atrapada en la red y no pasa nada en 240 τ. Cargar a garantiza que la grieta corra, a cambio de que el resultado no diga nada fino sobre el umbral.
En no hay periodicidad. Con el eje largo periódico, la entalla se cerraría sobre sí misma por el borde y tendría dos puntas: saldrían dos grietas corriendo una hacia la otra y chocarían en medio. Los bordes libres en cuestan que haya superficie donde no debería haberla, pero dejan una sola punta, que es lo que se quiere medir.
Antes de nada, la validación
En el artículo del nanohilo de cobre la validación consistía en comprobar que un potencial ajustado reproducía las tablas a las que se ajustó, que es un filtro necesario pero flojo. Aquí es distinto y mejor: las referencias son fórmulas, no datos experimentales.
Con solo primeros vecinos, el parámetro de red sale de , es decir , y la fórmula de Born para potenciales de pares en la red triangular se escribe entera:
lammps/in.elastico mide esas mismas magnitudes en LAMMPS, relajando la caja y deformándola
por diferencias centradas, y python/valida.py las compara:
| Magnitud | Unidad | LAMMPS | Analítico | Error relativo |
|---|---|---|---|---|
| Parámetro de red | σ | 1,1224620 | 1,1224620 | 2,8·10⁻¹⁵ |
| Energía de cohesión | ε/átomo | −2,0389902 | −2,0389902 | 2,3·10⁻¹⁴ |
| ε/σ² | 74,2354008 | 74,2354004 | 5,5·10⁻⁹ | |
| ε/σ² | 24,7451335 | 24,7451335 | 5,9·10⁻¹⁰ | |
| ε/σ² | 24,7451335 | 24,7451335 | 5,4·10⁻¹¹ | |
| Energía de superficie | ε/σ | 0,6055112 | 0,6055113 | 2,4·10⁻⁸ |
Esto no es «error del 1 %»: es coincidencia a nivel de redondeo. Y como las referencias son fórmulas y no medidas, lo que la tabla certifica es exactamente lo que interesa antes de simular: que la cadena de cálculo está bien montada. El fichero correcto, la red bien construida, las deformaciones del tamaño adecuado, las unidades sin un factor perdido.
Dos cosas que merecen un comentario:
La energía de superficie sale exacta, y tiene su gracia. Con solo primeros vecinos y , cada enlace está ya en su mínimo, así que al cortar el cristal los átomos del borde no sienten fuerza neta: la superficie no se relaja. El valor analítico —contar los enlaces que se rompen— es el valor correcto, y lo que queda de diferencia (0,000015 %) es la relajación residual que LAMMPS sí permite. En un cristal con más vecinos esto no pasaría, habría que medirla, y Griffith heredaría esa incertidumbre.
De la tabla sale todo lo demás sin tocar nada. El coeficiente de Poisson exacto; la isotropía elástica, que se comprueba con y cuadra a ; el módulo de Young bidimensional ; y de ahí las velocidades de onda, que son las que de verdad hacen falta:
todas en σ/τ, con . Esa última, , es la referencia contra la que se mide la grieta. No se ha ajustado nada para obtenerla: sale de una segunda derivada del potencial y de un poco de álgebra.
Detalle técnicoCómo se miden las constantes elásticas y γ, con la entrada de LAMMPS
Todo a 0 K y por minimización de energía, en una celda periódica de 20 × 12 celdas.
La red. Aquí está el primero de los dos tropiezos que cuestan una tarde: en units lj
el argumento de lattice es la densidad reducida, no el espaciado. Para que los
primeros vecinos caigan a en una red triangular —celda rectangular de
dos átomos y área — hace falta . Pasar el
espaciado deja la red comprimida un 10 % y, lo peor, todo lo demás sigue funcionando:
variable a0 equal 2.0^(1.0/6.0)
variable rho equal 2.0/(sqrt(3.0)*2.0^(1.0/3.0))
lattice custom ${rho} a1 1.0 0.0 0.0 a2 0.0 1.7320508075688772 0.0 &
a3 0.0 0.0 1.0 basis 0.0 0.0 0.0 basis 0.5 0.5 0.0
pair_style lj/cut 1.5
pair_coeff 1 1 1.0 1.0
pair_modify shift yesshift yes desplaza el potencial para que valga cero en el corte. Sin eso, cada enlace
arrastra un offset constante y la energía de cohesión —y con ella — sale mal.
El parámetro de red, relajando la caja en las dos direcciones y volviendo a minimizar sin la caja suelta:
fix relaja all box/relax x 0.0 y 0.0
min_style cg
minimize 0.0 1.0e-14 100000 1000000
unfix relaja
minimize 0.0 1.0e-14 100000 1000000Las constantes elásticas, por diferencias centradas con :
En 2D con la presión que devuelve LAMMPS ya es la tensión bidimensional, así que no hay que dividir por ningún espesor:
change_box all x final 0.0 $((1.0+v_eps)*v_lx0) remap units box
minimize 0.0 1.0e-14 100000 1000000
variable pxxp equal pxx
variable pxxP equal ${pxxp}
change_box all x final 0.0 ${lx0} remap units box
...
variable C11 equal -(${pxxP}-${pxxM})/(2.0*${eps})Y aquí el segundo tropiezo, que es el mismo que en el nanohilo y vuelve a morder: lx0
tiene que ser una instantánea numérica (variable lx0 equal ${lx0v}), no una variable
dinámica. Si se deja como equal lx, el change_box que «restaura» la caja la restaura al
valor ya deformado, la deformación se acumula y sale justo la mitad. Es un error
que no avisa: el número tiene unidades correctas y orden de magnitud razonable.
Para hay que pasar la caja a triclínica (change_box all triclinic), cizallar xy
y volver a ortho después.
La energía de superficie, abriendo la caja en una dirección y repartiendo la diferencia de energía entre las dos superficies que aparecen:
variable epot0 equal pe
variable e0 equal ${epot0}
change_box all boundary p s p
minimize 0.0 1.0e-14 100000 1000000
variable gamma equal (${epot1}-${e0})/(2.0*${lx0})El thermo_modify norm no de arriba es imprescindible: en units lj las magnitudes
extensivas salen normalizadas por átomo, y para hace falta la energía total.
Qué sale
La animación es la simulación, no un vídeo: el navegador reconstruye los 63 fotogramas y dibuja los átomos en vivo a partir de un binario de 960 KiB. La barra de abajo recorre la trayectoria a mano.

tensión σyy (ε/σ²)03,2
Cómo leer los colores. Cada átomo va pintado según , que es la componente que abre la grieta en modo I. Hay cuatro cosas que mirar, y las cuatro son física, no decoración:
- La lámina está entera en ámbar. Es la deformación aplicada de golpe: todo el cristal está cargado a la vez, a . (El primer fotograma, en t = 0, sale negro: la tensión que se pinta es una media de 20 pasos y en el instante cero todavía no hay ninguno. Es el único fotograma que no significa nada.)
- La entalla es una franja azul marino. Donde hay superficie libre no hay tensión que transmitir. Esa franja es la grieta inicial, y su longitud es el de la fórmula de Griffith.
- Delante de la punta hay un foco ámbar claro. Es la concentración de tensión, el de la solución elástica, resuelto átomo a átomo. Es lo que rompe el enlace siguiente, y viaja con la punta.
- Detrás de la punta queda una estela oscura que se va ensanchando. La grieta descarga el material que va dejando atrás: ahí ya no hay nada que tire, porque los dos labios están separados. Esa estela es la energía elástica que se está consumiendo, y cuando el triángulo oscuro llega arriba y abajo de la lámina, se acabó el combustible.
La velocidad frente al límite de Rayleigh
El resultado cuantitativo es la trayectoria de la punta. Se localiza en cada volcado mirando la franja central de la lámina y avanzando desde el borde izquierdo mientras no haya átomos: donde vuelve a haberlos, está la punta.
| Recorrido de la punta | de 60 σ a 250 σ: 190 σ |
| Velocidad en el tramo franco | 1,443 σ/τ |
| Velocidad de Rayleigh | 4,840 σ/τ |
| 0,298 |
Tres lecturas, por orden de lo que sostienen:
0,30 es un valor de libro para fractura frágil. La teoría dice que una grieta no puede superar —por encima, el balance de energía no se sostiene— y la experiencia dice que en la práctica se queda entre 0,2 y 0,5, con inestabilidades y ramificación cuando se acerca a la mitad. Que esta simulación caiga en 0,298 sin que nadie la haya empujado hacia ahí es la señal de que está haciendo mecánica de la fractura.
La escalera es el atrapamiento de red, en directo. La punta no avanza suave: se para en durante 25 τ, corre, se vuelve a parar cerca de 225 σ. Cada descanso es la punta enganchada entre dos filas de átomos, esperando a que una fluctuación térmica o la onda que vuelve de un borde le dé el empujón que le falta. Esto es exactamente lo que la teoría continua no puede tener: en Griffith la grieta o avanza o no avanza, no duda. Es también la razón de que la velocidad se mida sobre el tramo central y no sobre el recorrido completo: la media global mezclaría propagación con descansos y daría 1,07 σ/τ, un número que no corresponde a ningún régimen.
El frenazo del final no es un resultado, es el protocolo. A partir de t ≈ 210 τ la punta se queda en 250 σ y ya no se mueve. No es que el cristal aguante más ahí: es que la energía elástica almacenada se ha consumido, que es lo que tiene que pasar cuando se carga de golpe y no se sigue cargando. Dónde se para depende de cuánto se cargó, no de una propiedad del material.
Detalle técnicoLa entrada del ensayo de fractura, comando a comando
La lámina y la entalla. boundary s s p deja los dos bordes del plano libres y
shrink-wrapped. La entalla se abre borrando una banda de ±0,35 σ alrededor del plano
medio, que es poco más que una fila de átomos:
boundary s s p
region caja block 0 ${nx} 0 ${ny} -0.5 0.5 units lattice
create_atoms 1 box
variable ymed equal 0.5*(ylo+yhi)
variable xent equal xlo+${entalla}*lx
region corte block INF ${xent} $(v_ymed-0.35) $(v_ymed+0.35) INF INF units box
delete_atoms region corte compress yesLa carga, de golpe y afín. change_box ... remap reescala las posiciones de todos los
átomos junto con la caja, en lugar de estirar solo los bordes y esperar a que la
deformación se propague hacia dentro. Otra vez con la longitud de referencia congelada en
una variable numérica:
variable ly0v equal ly
variable ly0 equal ${ly0v}
change_box all y final $(ylo) $(ylo+(1.0+v_eps)*v_ly0) remap units boxEl contorno que mantiene la carga. Tres filas arriba y tres abajo con la fuerza puesta
a cero: no se mueven, así que la deformación impuesta no se relaja. El resto del cristal
integra en nve con un Langevin suave encima:
group borde union sup inf
group movil subtract all borde
velocity borde set 0.0 0.0 0.0
fix congela borde setforce 0.0 0.0 0.0
fix integra movil nve
fix termo movil langevin ${temp} ${temp} 1.0 ${semi} zero yes
fix dos all enforce2dzero yes le quita al termostato la deriva del centro de masas, y enforce2d mata
cualquier fuerza o velocidad fuera del plano en cada paso. Los dos son baratos y evitan
derivas que solo se notan tarde.
La tensión por átomo, promediada en el tiempo. compute stress/atom NULL devuelve el
virial por átomo —el NULL quita el término cinético—, en unidades de presión × volumen. En
2D el «volumen» por átomo es el área de su celda de Voronoi, :
compute sat all stress/atom NULL
variable Aat equal sqrt(3)/2*${a0}^2
fix prom all ave/atom 1 20 20 c_sat[2]
dump d1 all custom ${nvolc} ${sal}.lammpstrj id x y f_promEse fix ave/atom es la mitad de lo que hace legible la animación, y lo explica el apartado
siguiente.
El campo de tensión, y por qué hay que suavizarlo dos veces
La tensión de un solo átomo fluctúa muchísimo más que el campo macroscópico: es una magnitud instantánea de un objeto que está vibrando. Pintada en crudo, la lámina es confeti y no se ve nada. Se promedia dos veces, y las dos veces por razones distintas:
- En el tiempo, con
fix ave/atom 1 20 20dentro de LAMMPS: cada valor volcado es la media de 20 pasos. Quita el ruido térmico de alta frecuencia, que no es información sobre el estado de tensión. - En el espacio, con una gaussiana de 1,6 σ en
python/campo.py, hecha con una rejilla para que sea . Esto no es cosmética: el campo de tensión del que habla la mecánica del continuo es un promedio sobre un volumen que contiene muchos átomos. Suavizar es construir la magnitud que se quiere comparar con la teoría, no disimular la que hay.
El mapa de color va de azul marino a ámbar pasando por arena, interpolando en espacio Lab con luminosidad creciente, de modo que la imagen se sigue leyendo en escala de grises o con daltonismo; los extremos son los dos colores de la marca. Y el rango se satura en , no en el máximo: la singularidad de la punta es tan aguda que, escalando al máximo, todo lo demás queda plano. Es una decisión de visualización que cambia lo que se ve, así que va dicha: el ámbar más claro significa «3,2 ε/σ² o más».
Qué no demuestra esto
Cuatro límites, por orden de importancia:
La comparación con es con un límite, no con un valor. Esta es la más importante y la más fácil de vender de más. Las constantes elásticas y sí son comparaciones exactas contra fórmulas cerradas: ahí se puede decir «coincide». La velocidad de la grieta no: la teoría dice y la simulación da . Eso es compatible con la teoría, no una predicción acertada. Una comprobación de verdad del régimen de velocidades pediría barrer la carga aplicada y ver que crece hacia el límite sin cruzarlo, que es lo que dice la teoría dinámica de la fractura y lo que este montaje no hace.
Griffith aquí solo da el orden de magnitud. Se carga a 4,5 veces la crítica porque por debajo de unas 2,5 veces la grieta no arranca. Es decir: el umbral real de esta lámina está bastante por encima del de Griffith, y la diferencia es el atrapamiento de red. La fórmula sigue siendo útil —dice en qué orden de magnitud buscar la carga— pero no es una predicción cuantitativa en un sistema de este tamaño, y presentarla como tal sería hacer trampa.
El cristal es bidimensional y el potencial es de juguete. Dos dimensiones no son tres: no hay dislocaciones de tornillo, no hay planos de deslizamiento que compitan, y la superficie nueva es una línea. Y un Lennard-Jones cortado entre vecinos no es ningún material: es el sistema modelo más simple que todavía se rompe. La ventaja es justamente esa —permite referencias exactas—, pero lo que se mide aquí son propiedades de este modelo. Lo que es transferible es el método y el mecanismo, no los números.
Una ejecución, una semilla. La grieta arranca y se para por sucesos individuales, y
cuáles son depende de las velocidades iniciales. Para dar la velocidad con una barra de
error —y para decir dónde está de verdad el umbral de arranque— habría que repetir con
varias semillas y varias cargas. Son dos barridos que este montaje permite (EPS es una
variable de entorno) y que este artículo no hace.
Nada de esto quita valor al cálculo; lo encuadra. Lo que sí sostiene este trabajo es la cadena entera: un cristal cuyas propiedades elásticas se conocen en cerrado y se reproducen a nivel de redondeo, una grieta que corre a una fracción sensata del límite teórico, y un campo de tensión que se puede mirar átomo a átomo y se comporta como la solución elástica dice.
Cómo reproducirlo
Todo está en github.com/djoroya/sim-visuales, en
md/grieta-2d/. Un solo script:
./run.sh # validación + simulación + salidas
./run.sh validacion # solo las constantes elásticas y γ
./run.sh simulacion # solo el ensayo de fractura (unos 3 minutos)
./run.sh salidas # vídeo, imágenes y datos del visor
Hace falta LAMMPS sin paquetes especiales —lj/cut y enforce2d van en el núcleo—,
ffmpeg, y Python 3 con numpy, matplotlib y Pillow; el script crea el entorno virtual la
primera vez. Las variables útiles son NX y NY (celdas de la lámina), EPS (la
deformación aplicada), TFIN y HILOS.
El volcado completo son 283 MB y se queda en datos/, fuera de git. Lo que se versiona es
lo reproducible: las dos entradas de LAMMPS, los scripts de Python y las salidas pequeñas.
Detalle técnicoCómo caben 43.519 átomos en 960 KiB, y qué descarga esta página
El volcado de la simulación son 283 MB de texto. Lo que llega al navegador son 960 KiB, y sale de tres recortes y un truco.
Los recortes, porque dibujar los átomos de verdad tiene un suelo de tamaño —del orden de 1,5 bytes por átomo y fotograma una vez comprimido—, y 43.519 átomos por 240 fotogramas serían 30 MB:
- Fuera las filas congeladas, 7 σ arriba y abajo: su tensión es artificial, la impone
setforce, y saturaría el color justo en los bordes. Quedan 39.311 átomos. - Uno de cada cuatro átomos, tomando una subred triangular de parámetro en lugar de uno de cada cuatro por índice. La diferencia importa: por índice quedarían huecos irregulares y el ojo los lee como defectos. Quedan 9900.
- Uno de cada dos volcados: 63 fotogramas de los 240.
Y el truco, el mismo que en el nanohilo: guardar incrementos entre fotogramas en lugar de
posiciones absolutas. Entre dos fotogramas un átomo se mueve centésimas de σ: números
pequeños y muy repetidos, que es de lo que vive gzip. El primer fotograma va en uint16 con
los planos de byte separados y el resto son int8 de diferencia, con el incremento calculado
contra la posición que va a reconstruir el visor y no contra la exacta, para que el error
no se acumule: el máximo de reconstrucción es 0,01 σ, la centésima parte de un radio
atómico. La tensión va en un byte por átomo y fotograma.
Lo que descarga de verdad quien lee esta página:
| Transferido | |
|---|---|
| El artículo entero (HTML + CSS) | ≈ 16 KiB |
| Póster PNG, en el HTML y compartido por los dos visores | 160 KiB |
| El cargador diferido, dentro del módulo de la página | < 1 KiB |
| El visor, nada más abrir (la animación está arriba) | ≈ 3 KiB |
Trayectoria .crack, una sola vez para los dos visores | 960 KiB |
| Subtotal: la animación de cabecera en marcha | ≈ 1,1 MiB |
| La gráfica de la punta, al llegar hasta ella | 6 KiB |
| Sin JavaScript: texto, póster y gráfica | ≈ 182 KiB |
El visor no tiene dependencias: son diez mil discos en un canvas 2D, así que no hay three.js
que empaquetar. Con tantos átomos, arc() + fill() uno a uno no da 60 fps, de modo que
precalcula 32 «sellos» —un disco ya pintado en cada nivel de color— y cada átomo es un
drawImage, que el navegador resuelve copiando píxeles.
El cargador es un IntersectionObserver de menos de 1 KB que no pide nada hasta que su
figura está a 300 px de entrar en pantalla. Y si has pedido menos movimiento en tu
sistema, los dos visores se comportan distinto a propósito: la animación de la cabecera no
llega a montarse —el póster ya es el fotograma fijo que estás pidiendo—, mientras que este
de aquí sí, porque aquí la simulación es el contenido del artículo; se monta parado, en un
instante representativo, con la barra de tiempo para recorrerlo a mano. La escala de color va
en el HTML y no la dibuja el visor, para que se lea también en ese caso.
Por qué el fondo de la portada de esta web es un vídeo y esto un canvas. El mismo plano, renderizado como campo continuo y comprimido en vídeo, pasa de 409 KiB (átomos) a 170 KiB con mejor calidad: el retículo de discos es ruido de alta frecuencia y es justo lo que más caro le sale a un códec. Donde hace falta ir por debajo de 300 KiB y el detalle atómico compite con un titular, gana el vídeo. Donde la simulación es el contenido y se quiere poder pararla, gana el canvas.