In questi giorni, leggendo
La scoperta dei frattali cosmici mi sono chiesto se uno strumento come SQL Server potesse essere d'aiuto in alcuni pesanti calcoli astronomici, e ho riflettutto un po' sulla possibilità di spremerlo in ambito di evoluzione dei sistemi dinamici.
Venendo subito al sodo, avendo una tabelle di masse e relative posizioni e velocità [sul piano negli esempi che seguono, ma per passare al 3D bastano un paio di modifiche banali]:
create table t_m(id smallint identity primary key,
m float not null,
x float not null,
y float not null,
vx float not null,
vy float not null)
è possibile estrarre l'accellerazione, divisa per componente, subita dall'i-esimo corpo e dovuta all'interazione gravitazionale con i restanti corpi con una semplice vista del tipo:
create view v_a
as
select id,
ax=sum(m2*(x2-x)/power(d2,1.5)),
ay=sum(m2*(y2-y)/power(d2,1.5)) from(
select m2.id id2,m1.*,d2=power((m1.x-m2.x),2)+power((m1.y-m2.y),2),m2.x x2,m2.y y2,m2.m m2
from t_m m1
inner join t_m m2
on m1.id!=m2.id)d
group by d.id
Dove le unità di misura sono scelte opportunamente in modo da avere la costante universale G=1.
Fatto ciò potremmo scrivere una stored banalissima per aggiornare le posizioni e le velocità in seguito ad un passo quantizzato di tempo alla maniera di:
create procedure p_Step @t float
as
set ansi_warnings off
update t_m set
vx=vx+ax*@t,vy=vy+ay*@t,
x=x+vx*@t,y=y+vy*@t
from t_m
inner join v_a a
on a.ID=t_m.id
in cui quel 'set ansi_warnings off' evita fastidiose divisioni per zero.
Sembra incredibile ma è tutto, questi tre banali oggetti ci permettono di studiare l'interazione gravitazionale di n corpi, un piccolo test su 1000 corpi generati casualmente potrebbe essere:
declare @i int,@rnd1 float,@rnd2 float,@rnd3 float, @rnd4 float,@rnd5 float
set @i=0
while @i<1000
begin
select @rnd1=rand()*10,@rnd2=rand()*10,@rnd3=rand()*10,@rnd4=rand()*10,
@rnd5=rand()*10
insert into t_m values(@rnd5,@rnd1,@rnd2,@rnd3,@rnd4)
set @i=@i+1
end
e questo sistema possiamo farlo evolvere e verificarne il nuovo stato dopo 0.1 unità temporali [in quell'unità di misura di cui sopra] con un banale:
exec p_Step 0.1
select * from t_m
Serve a qualcosa questo giochino? Boh.
Una cosa è certa, con 1000 corpi occorre valutare un milione di interazioni e con un database SQL si ottiene banalmente il risultato con quel:
from t_m m1
inner join t_m m2
on m1.id!=m2.id
e tale strumento è ottimizzato per la gestione di queste grosse moli di dati. Inoltre basta disporre di un bel serverone multiprocessore per ottenere un calcolo in parallelo su tutte le interazioni senza dover scrivere una riga di codice. Ultimo dettaglio, non meno importante, gli step in un db possono essere agevolemnte archiviati tutti quanti, se richiesto, fatto questo che per una tradizionale applicazione risulta decisamente ostico.
Non credo che alla NASA usino SQL Server per questi calcoli, ma, appena ho una macchina libera metto alla prova la tecnica in discussione su un migliaio di corpi distribuiti nello spazio, voglio vedere se si creano queste benedette strutture frattali o se il sistema resta tuttosommato casuale.
Vi farò sapere, marc.