kelvin@cluxnei.dev:~/blog

kelvin@cluxnei:~/blog$ cat simulando-o-universo.md

2026-09-12 PT ~25 min de leitura read in English

Simulando o universo: a física por trás de 700 corpos numa aba do navegador

Este texto é uma exploração, não uma história. Vamos abrir o motor de uma simulação gravitacional e olhar cada peça: as equações e para que servem, os nomes reais das técnicas, os números medidos de desempenho, e a parte que quase ninguém escreve, que são os lugares onde a simulação mente de propósito, com o custo da mentira calculado.

Disco protoplanetário, 681 corpos, 6,1 anos simulados. Uma estrela e um disco de embriões planetários. Cada ponto é um corpo com massa, raio, densidade e composição química próprias, sentindo a gravidade de todos os outros.

Neste texto

  1. A física, do começo: todas as fórmulas e para que cada uma serve
  2. Unidades: por que G = 4π²
  3. A singularidade e o softening de Plummer
  4. O integrador, e como saber se ele está certo
  5. Barnes-Hut: trocar exatidão por tempo
  6. Por que toda estrela é somada exata
  7. Composição: fusão em cadeia alfa
  8. As licenças poéticas
  9. Ruptura por maré: o teste contra a natureza
  10. O que foi deliberadamente recusado

A física, do começo

Antes de olhar o código, vale montar o vocabulário inteiro. São poucas fórmulas e cada uma responde a uma pergunta específica.

A única força que existe aqui

Tudo começa com a lei da gravitação universal de Newton. Dois corpos de massa m₁ e m₂, separados por uma distância r, se atraem com força:

F= G m1⁢m2 r2

G é a constante gravitacional e r a distância entre os centros. A força cresce com as duas massas e cai com o quadrado da distância.

Dois fatos fazem dessa fórmula simples um problema difícil. O primeiro é que a força cai com o quadrado da distância, mas não chega a zero nunca: todo corpo puxa todo corpo, para sempre. O segundo é que aceleração é força dividida por massa, então a aceleração que um corpo i sofre é a soma das contribuições de todos os outros:

a→i = ∑j≠i G⁢mj (r→j − r→i) |r→j − r→i| 3

O vetor no numerador dá a direção do puxão. O expoente 3 no denominador é o quadrado da lei de Newton mais um fator que vem de normalizar esse vetor, já que ele não tem comprimento unitário.

Com dois corpos isso tem solução exata, que são as elipses de Kepler. Com três ou mais, não tem. Poincaré mostrou no fim do século XIX que não existe solução fechada geral para o problema de N corpos. É por isso que se simula: não porque a matemática seja desconhecida, mas porque a única forma de saber onde os corpos estarão daqui a um ano é avançar o tempo em passos pequenos e somar.

Densidade, raio e as quantidades derivadas

Um corpo não tem raio arbitrário. Dados massa e densidade, o raio é consequência de assumir uma esfera:

r= 3⁢m / (4⁢π⁢ρ) 3

A raiz cúbica do volume. Se o raio fosse um parâmetro livre, daria para ter um planeta do tamanho de Júpiter com a massa da Terra.

Amarrar o raio à densidade é a diferença entre um modelo e uma animação: a partir daqui, colisões, marés e densidades passam a significar alguma coisa.

A temperatura no centro de uma estrela sai de um argumento de equilíbrio: a pressão do gás tem que segurar o peso das camadas de cima. Disso vem uma estimativa conhecida como temperatura virial:

Tc≈ G⁢M⁢μ⁢mH kB⁢R

μ é o peso molecular médio, mH a massa do átomo de hidrogênio e kB a constante de Boltzmann.

Aplicada ao Sol, ela dá 1,39 × 10⁷ K contra os 1,57 × 10⁷ K reais, ou seja 12% de erro com uma linha de conta. É boa o suficiente para decidir o que queima e o que não queima.

As distâncias que decidem o comportamento

Três raios aparecem o tempo todo, e cada um marca a fronteira de um regime diferente.

A esfera de Hill é a região onde a gravidade de um corpo ganha da estrela que ele orbita. É o território dele:

rH= a⁢ m/(3⁢M) 3

a é o semieixo da órbita, m a massa do corpo e M a da estrela.

O raio de maré é onde a diferença de gravidade entre o lado próximo e o lado distante de um corpo supera a gravidade que o mantém inteiro. Passou disso, ele se despedaça:

rmaré≈ R⁢ 2⁢M/m 3

R e m são o raio e a massa do corpo que se aproxima, M a massa do corpo central.

E o raio de Schwarzschild é o horizonte de eventos de um buraco negro, a distância em que a velocidade de escape iguala a da luz:

rs= 2⁢G⁢M c2

Guarde esse último. A comparação entre r_s e as outras escalas da simulação vai decidir, mais adiante, o que vale a pena simular e o que é decoração.

Unidades: por que G = 4π²

No Sistema Internacional, a constante gravitacional é 6,674 × 10⁻¹¹ m³·kg⁻¹·s⁻². É um número horrível para trabalhar: as massas ficam na ordem de 10³⁰, as distâncias em 10¹¹, e um float64 gasta boa parte da precisão só carregando expoente.

A saída clássica em astronomia é trocar as unidades. Se você medir massa em massas solares, distância em unidades astronômicas e tempo em anos, algo bonito acontece.

Considere uma órbita circular. A aceleração centrípeta tem que ser exatamente a gravidade:

v2r = G⁢Mr2 ⟹ v= G⁢Mr

Agora imponha a definição da própria unidade astronômica: um corpo a 1 UA de uma estrela de 1 M☉ completa a volta em 1 ano. A velocidade dessa órbita é o perímetro dividido pelo período, ou seja 2π. Substituindo r = 1 e M = 1:

2π=G ⟹ G=4π2 ≈39,478

A constante deixa de ser uma medida experimental e vira uma identidade forçada pela escolha das unidades.

E isso entrega de graça o melhor teste que essa simulação tem. Está escrito como doutrina no cabeçalho de units.js:

Coloque um corpo a 1 UA com velocidade 2π UA/ano e ele tem que fechar a órbita em exatamente um ano.

É um teste falsificável que não depende de nenhuma outra parte do código estar certa. Se ele falhar, a base está errada e não adianta olhar mais nada.

Painel de estado da simulação mostrando 777 corpos, linha de gelo em 2,68 UA e as energias cinética e potencial
O painel de estado. Repare nas duas últimas linhas: energia cinética 0,0063 e potencial −0,0126. A razão é exatamente ½, ou seja 2K + U = 0. Isso é o teorema do virial, a assinatura de um sistema gravitacional em equilíbrio. O número não foi imposto: ele emerge.

A singularidade e o softening de Plummer

A lei de Newton tem um defeito fatal para quem simula: quando r → 0, a força vai para o infinito. Dois corpos que passam muito perto recebem uma aceleração absurda em um único passo de tempo e saem disparados, e a simulação explode. Não é um bug de implementação. É a fórmula sendo honesta sobre uma situação que o passo de tempo não consegue resolver.

A solução ingênua é limitar a aceleração num teto arbitrário. Funciona no sentido de que nada voa para o infinito, mas é fisicamente indefensável: toda vez que o limitador dispara, você está injetando ou removendo energia do sistema sem que nada físico tenha acontecido.

A solução usada aqui é o softening de Plummer, que adiciona um comprimento ε ao denominador:

F= G⁢m1⁢m2 r (r2+ε2) 3/2

Com ε = 10⁻³ UA, cerca de um quinto de um raio solar. Para r ≫ ε é indistinguível de Newton; para r → 0 a força tende suavemente a zero em vez de explodir.

Não há descontinuidade, não há energia criada do nada, e ainda economiza uma normalização de vetor que poderia gerar NaN quando a distância é exatamente zero.

O critério para escolher ε é simples de enunciar: ele precisa ser muito menor que as separações orbitais que interessam, ou distorceria as próprias órbitas que queremos medir. Um quinto de raio solar contra separações de ordem 1 UA passa folgado. O efeito medido no fechamento de uma órbita de teste é desprezível: erro de fase 1,030 × 10⁻³ rad com softening ligado contra 1,011 × 10⁻³ rad desligado.

Guarde este número. O comprimento de suavização de 10⁻³ UA vira, no resto do projeto, uma régua de honestidade: qualquer efeito físico que aconteça numa escala menor que essa não está sendo resolvido, e fingir que está seria decoração. Esse argumento vai reaparecer duas vezes.

O integrador, e como saber se ele está certo

Integrar significa: dado onde os corpos estão e a aceleração que sentem, descobrir onde estarão um instante depois. O método mais simples é o de Euler, que avança a posição usando a velocidade atual e a velocidade usando a aceleração atual. É de primeira ordem, e na prática as órbitas precessam visivelmente e a energia deriva.

O método usado aqui é o Velocity-Verlet, que custa quase o mesmo, já que basta guardar a aceleração do passo anterior, e é de segunda ordem:

x(t+Δt) = x(t) + v(t)⁢Δt + 12 ⁢a(t)⁢ Δt2 v(t+Δt) = v(t) + 12 [ a(t)+ a(t+Δt) ] ⁢Δt

A velocidade usa a média entre a aceleração antiga e a nova. É daí que vem a ordem 2.

Além da ordem, ele tem uma propriedade que importa muito em gravitação: é simplético. A energia não deriva sistematicamente para cima ou para baixo, ela oscila em torno do valor certo. Uma órbita fechada continua fechada depois de milhares de voltas.

A parte que realmente prova alguma coisa

"Parece funcionar" não é verificação. A forma correta de testar um integrador é medir sua ordem de convergência: se ele é de segunda ordem, dividir o passo por k tem que dividir o erro por k².

passo de integraçãoerro de fase após uma órbita
Δt = 1/286 ano1,030 × 10⁻³ rad
Δt = 1 × 10⁻⁴ ano8,27 × 10⁻⁷ rad
redução do passo:  35×
redução do erro:   1222×
esperado (35²):    1223

O integrador tem exatamente a ordem de convergência que a teoria prevê. Essa é uma afirmação que podia ter saído falsa, e é isso que a torna útil.

O passo de tempo é do cenário, não do programa

Um detalhe de engenharia com consequência física direta: não existe um passo de tempo global. Cada cenário publica o seu, porque uma binária apertada precisa de um passo muito menor que um disco de 20 UA, e reusar o do disco quebraria a binária visivelmente.

O critério vem da órbita mais interna, que é sempre a mais rápida. No disco padrão ela leva cerca de 0,35 ano, e o Velocity-Verlet quer bem mais de 20 passos por órbita:

FIXED_DT = 0,0035 ano   cerca de 100 passos na órbita interna

É também por isso que os cenários de buraco negro rodam muito mais devagar no seu navegador: perto de um corpo de 10⁶ M☉ o passo necessário é minúsculo, e cada segundo de relógio cobre muito menos tempo simulado.

Barnes-Hut: trocar exatidão por tempo

Calcular a força entre todos os pares de n corpos custa O(n²). Com 800 corpos são 319.600 pares por passo, e a 100 passos por órbita isso vira muita conta.

O algoritmo de Barnes-Hut resolve isso com uma observação simples: um aglomerado distante de corpos puxa aproximadamente igual a uma única massa pontual no centro de massa dele. Divide-se o espaço num octree, em que cada cubo se subdivide em oito até sobrar um corpo por célula, e ao calcular a força sobre um corpo percorre-se a árvore decidindo célula a célula pelo critério de abertura:

sd <θ

s é a largura da célula e d a distância do corpo até o centro de massa dela. Se a razão for menor que θ, a célula inteira vira uma massa só; caso contrário, desce-se para as oito subcélulas.

Isso derruba o custo para O(n log n). O preço é erro, e o erro é medido, não estimado:

θerro relativo médioerro máximoobservação
0,5 (desktop)0,53%2,80%padrão
0,8 (celular)maiormaiormetade do custo do passo de gravidade
→ 02,7 × 10⁻¹⁵ converge para a força bruta, como deve

Aquela última linha é outro teste falsificável: com θ tendendo a zero, a árvore deixa de aproximar qualquer coisa e tem que reproduzir a soma direta. Reproduz, com quinze casas.

A honestidade desconfortável

Barnes-Hut é a otimização mais citada em simulação de N corpos. Nesta escala, porém, o ganho medido foi:

800 corpos:    ~1,1×   o cruzamento fica bem aqui
~2000 corpos:  ~2,2×   a partir daqui compensa de verdade

Com a contagem padrão, a árvore quase não paga o próprio custo de construção. Ela está lá porque o número de corpos é ajustável e o usuário pode pedir 4000, mas seria desonesto vendê-la como a razão de a simulação ser rápida.

Aglomerado estelar. As massas das estrelas são sorteadas da função de massa inicial de Kroupa, a distribuição medida em aglomerados reais, com muitas anãs vermelhas e poucas gigantes. As velocidades são postas em equilíbrio virial, o mesmo 2K + U = 0 que apareceu no painel lá em cima.

Por que toda estrela é somada exata

Aqui está uma decisão que vale mais que a otimização inteira. A árvore de Barnes-Hut é aplicada apenas aos corpos leves. Toda estrela é somada exatamente, corpo a corpo, fora da árvore.

O raciocínio: as estrelas carregam quase toda a massa do sistema. A órbita de cada corpo leve é, essencialmente, a órbita dele em torno desses poucos termos. Aproximar as estrelas por um multipolo colocaria o erro justamente onde ele domina o resultado, o que seria economizar no lugar errado. E como existem de um punhado a algumas centenas de estrelas, o custo é O(S·n) e exato, contra O(n log n) e aproximado para todo o resto.

As duas passagens tocam pares disjuntos: a árvore nunca vê uma estrela, e a soma direta cobre todo par que envolve uma. Nada é contado duas vezes, nada é esquecido.

Um buraco negro também entra nessa lista, e o comentário no código faz questão de dizer que isso não é uma afirmação de que ele brilha. É apenas o conjunto da soma direta, e um buraco é o objeto mais pesado de qualquer sistema que o contenha.

O momento que a árvore quebra, e a correção

Há um efeito colateral sutil. As forças calculadas pela árvore não são simétricas entre pares: o corpo A sente a célula que contém B, mas B sente uma célula diferente que contém A. A terceira lei de Newton deixa de valer exatamente, e sobra uma força líquida espúria sobre o sistema inteiro.

A correção é elegante. Some essa força líquida e subtraia-a como uma aceleração uniforme de todos os corpos que passaram pela árvore. Isso restaura a condição abaixo sem alterar nenhuma aceleração relativa, e portanto sem tocar em nenhuma órbita:

∑i mi⁢ a→i =0

A força líquida sobre um sistema isolado tem que ser zero. Qualquer valor diferente disso é erro do método, não física.

força líquida bruta da árvore:   6 × 10⁻³
depois da correção:              3,9 × 10⁻¹⁶

medido com 800 corpos, após 531 fusões
Binária com disco circumbinário. O disco não começa em qualquer lugar: ele começa fora do limite de estabilidade de Holman-Wiegert, o raio calculado a partir da separação, da razão de massas e da excentricidade do par, dentro do qual nenhuma órbita sobrevive. É onde os planetas circumbinários reais vivem.

Composição: fusão em cadeia alfa

Cada corpo carrega uma composição química. Não um rótulo, mas frações de massa de oito espécies da cadeia alfa, que é a sequência de fusão que governa a vida de uma estrela:

H → He → C, O → Ne, Mg → Si → Fe

cada etapa precisa de uma temperatura central maior que a
anterior. O ferro é o fim da linha, porque fundir ferro
consome energia em vez de liberar.

A temperatura central de cada corpo é recalculada a cada passo pela fórmula virial da introdução, e ela decide qual etapa está acesa. Isso é um equilíbrio, não uma integração: o tempo térmico de uma estrela e o tempo dinâmico diferem por ordens de grandeza. O tempo de Kelvin-Helmholtz do Sol é de dezenas de milhões de anos, o dinâmico é de meia hora. Na escala do passo, a estrutura térmica é quase estática, e calcular o equilíbrio sai mais barato e mais estável que evoluí-lo.

O bug que só um teste pegaria

A cadeia como especificada inicialmente tinha estados absorventes: nitrogênio e magnésio não tinham saída. Um núcleo a 5 × 10⁹ K, quente o bastante para chegar ao ferro, terminava com 69% de magnésio e parava ali.

A correção foi adicionar as duas transições que faltavam: N → O, já que o nitrogênio é catalisador do ciclo CNO mas é destruído por captura alfa quando o hélio acende, e Mg → Si. O comentário que ficou no código resume o invariante:

O ferro é o único estado absorvente desta cadeia, e esse é justamente o ponto.

Outro caso do mesmo tipo: o limiar de ignição, se fosse só por temperatura, acenderia anãs marrons. A estimativa virial erra por um fator de cerca de 4 perto do limite, porque em objetos muito pequenos quem segura a estrela é a pressão de degenerescência dos elétrons, que não custa calor. Hoje a ignição é condicionada à massa, e o resultado é o correto:

0,079 M☉  →  anã marrom, T_c = 1,22 × 10⁷ K, não queima nada
0,080 M☉  →  estrela, queima

As licenças poéticas

Esta é a seção que eu mais queria escrever, porque é a que costuma ficar de fora. Toda simulação mente em algum lugar. A diferença entre um modelo e uma animação é se as mentiras estão marcadas e se o custo delas foi calculado.

1. O raio de captura, e a maior mentira do projeto

Em escala real, um planeta tem raio de ordem 10⁻⁵ UA contra separações orbitais de ordem 1 UA. A seção de choque geométrica é tão absurdamente pequena que um disco real leva de 10⁷ a 10⁸ anos para formar planetas. Numa aba de navegador, nada jamais aconteceria.

Então o raio de captura é multiplicado por 800. Isso comprime a formação planetária em alguns milhares de anos simulados. O que salva isso de ser um truque é o que vem junto:

E a fronteira entre licença e física está demarcada em uma linha do código. O foco gravitacional, que aumenta a seção de choque por um fator (1 + v_esc²/v_rel²) e importa quando a velocidade relativa é baixa, é física real, não licença.

Há também uma mentira que foi conscientemente não cometida: a estrela central absorve a 10 raios solares, não a 800. O comentário explica por quê, já que 800 vezes daria 3,7 UA e ela comeria o disco inteiro.

2. O tamanho desenhado

Um raio solar é 0,00465 UA. Num disco de 20 UA, um planeta em escala real ocupa alguns milionésimos da cena: a tela seria preta. Os corpos são desenhados inflados, numa curva compressiva de expoente 0,55, para que um Júpiter não engula uma Terra pelo fator que engoliria de verdade.

O valor dessa escala foi ajustado por medição, não por gosto. Com o valor que parecia razoável de início, a faixa dinâmica inteira colapsava:

escala de renderfaixa dinâmica resultanteefeito na tela
12001,32×de pedregulho a estrela, tudo vira a mesma bola de 3 UA
615,6×dá para distinguir as classes
Nota sobre as imagens deste post. Os vídeos foram capturados em renderização por software, que deixa a cena bem mais escura do que no seu navegador com GPU. Todos passaram pelo mesmo pós-processamento: recorte central, upscale e ajuste de níveis. A física não foi tocada. O que foi ajustado foi brilho e enquadramento.

Ruptura por maré: o teste contra a natureza

Quando uma estrela passa perto demais de um buraco negro supermassivo, a diferença de gravidade entre o lado de perto e o lado de longe supera a gravidade própria dela e ela se despedaça. Metade dos destroços fica ligada e volta, a outra metade escapa. É um evento real, observado dezenas de vezes, e tem uma assinatura característica.

A pergunta de projeto era se dava para simular isso sem hidrodinâmica. A resposta veio de comparar o raio de maré com o comprimento de suavização, aquela régua de honestidade da seção anterior:

buraco negroraio de maréem unidades de softening
10 M☉0,0100 UA10×, marginal
10⁴ M☉0,1002 UA100×
10⁶ M☉0,4650 UA465×
Sgr A*0,7562 UA756×

Num buraco supermassivo, a região onde a estrela se despedaça é centenas de vezes maior que a escala em que a simulação já deixou de resolver. Ou seja: não é preciso fingir. Ao cruzar o raio de maré, a estrela é substituída por 600 corpos que carregam a massa e a composição dela, e a física que já existia faz o resto. As partículas da frente orbitam mais rápido que as de trás, e o esticamento aparece sozinho.

A espaguetificação deixa de ser desenhada e passa a ser consequência.
Painel descrevendo o cenário de ruptura por maré com raio de maré, periastro, horizonte e a lei de retorno
O cenário se explica. Raio de maré 0,465 UA, periastro em metade disso, horizonte de eventos em 0,0197 UA, e a observação de que o horizonte está resolvido a 20 comprimentos de suavização. A última linha é a mais importante: não há hidrodinâmica; os fragmentos são massas gravitacionais, não fluido.

Não funcionou de primeira, e o motivo importa

Na primeira tentativa, os fragmentos foram distribuídos ao longo de um raio solar. Isso os deixou a 1,5 × 10⁻⁵ UA uns dos outros, 65 vezes mais perto que o comprimento de suavização. E abaixo do softening, o kernel de Plummer não é gravidade: é uma mola linear.

O resultado foi imediato e inequívoco. A distribuição de energia colapsou em quatro picos em menos de 100 passos, e o expoente ajustado deu −0,41, com r² = 0,04. Não era uma imprecisão. Era o modelo descrevendo outra coisa.

A correção foi alargar o fluxo até o espaçamento médio ser alguns comprimentos de suavização. E foi classificada, no próprio código, como licença poética da mesma espécie do fator 800, porque é exatamente isso que ela é.

O resultado

A assinatura observacional de um evento de ruptura por maré é a taxa de retorno dos destroços seguindo uma lei de potência:

dMdt ∝ t−5/3

O expoente −5/3 = −1,667 é medido em dezenas de eventos reais. Este é um teste contra a natureza, não contra uma fórmula.

medidavalorreferência
expoente de retorno−1,706 (r² 0,9965)−1,667 teórico
fração ligada48,0% (288/600)50% esperado
espalhamento de energia8,4769 × 10⁵8,4891 × 10⁵ previsto
massa conservada na ruptura2,4 × 10⁻¹⁴2 → 601 corpos
momento conservado1,9 × 10⁻¹⁶ 

O expoente sai cerca de 2,5% mais íngreme que o teórico, de forma consistente, e a causa foi diagnosticada em vez de varrida para baixo do tapete: faltam retornos tardios no fim da janela, o que inclina o ajuste. O ajuste puramente kepleriano sobre as energias iniciais dá −1,663.

A aproximação e a ruptura. A estrela cai numa órbita praticamente parabólica e é despedaçada ao cruzar 0,512 UA, em t = 0,00613 anos. Este é o cenário mais caro da simulação: perto de um corpo de 10⁶ M☉ o passo de tempo necessário é minúsculo.

Onde não funciona

Com um buraco negro estelar de 10 M☉, a conservação continua exata e a divisão ainda é meio a meio, mas o resultado físico não presta. Nessa massa, o raio de absorção da própria estrela é cinco vezes maior que o raio de maré, então a "ruptura" dispara a nove raios de maré, longe de onde deveria. O cruzamento útil fica em torno de 10⁴ M☉.

O que foi deliberadamente recusado

A decisão mais madura do projeto inteiro é uma coisa que não foi implementada.

Perto de um buraco negro, a gravidade newtoniana está errada. Existe um atalho conhecido para capturar os efeitos relativísticos sem resolver Einstein, o potencial pseudo-newtoniano de Paczyński-Wiita:

Φ= − G⁢M r−rs

Reproduz a última órbita circular estável (ISCO) em 3·r_s e o mergulho para dentro dela, sem resolver relatividade geral.

Seria fácil de adicionar e renderia uma boa linha no README. Foi recusado, e o motivo está gravado no código com o pedido explícito de que ninguém o adicione por engano depois. A conta:

buraco de 10 M☉:
  r_s          = 1,97 × 10⁻⁸ UA
  ISCO (3·r_s) = 6 × 10⁻⁷ UA
  softening    = 1 × 10⁻³ UA

a ISCO fica 4 a 5 ordens de grandeza ABAIXO da escala
em que a força já é deliberadamente errada

Seria decoração pintada sobre um lugar que a simulação não resolve, ao custo de um caso especial no laço mais quente do programa e da conservação exata de momento. Para efeito de comparação: num buraco de 10⁶ M☉ a razão r_s / softening é 19,7, e aí sim o horizonte é resolvível. Por isso buracos negros supermassivos entraram e a relatividade não.

Pelo mesmo critério ficou de fora a hidrodinâmica de verdade (SPH). Precisaria de pressão, choques e uma equação de estado, e mudaria o caráter do projeto inteiro. Os fragmentos da ruptura são massas gravitacionais, e o texto do próprio cenário diz isso ao usuário.

O resumo

Se der para levar uma coisa só deste texto, que seja o critério que aparece em todas as seções: escolher a escala em que você está disposto a errar, e então recusar tudo o que acontece abaixo dela.

O comprimento de suavização define essa escala. Ele justifica o softening, justifica a recusa da relatividade, condena a primeira versão do fluxo de destroços e decide quais buracos negros valem a pena. Um único número, aplicado com consistência, faz mais pela honestidade de um modelo do que qualquer quantidade de física adicionada por cima.

Colisão estelar. Duas estrelas em rota de colisão, cada uma com seu disco. Com parâmetro de impacto pequeno elas se fundem; aumentando-o, passam raspando e arrancam os discos uma da outra.

A simulação está em cluxnei.dev/universe-simulation/ e roda inteira no seu navegador, sem servidor e sem instalação. O código está no GitHub, incluindo todos os comentários citados aqui, que são a melhor parte.

kelvin@cluxnei:~/blog$