IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Téléchargé 4 fois
Vote des utilisateurs
1 
0 
Détails
Licence : Non renseignée
Mise en ligne le 1er avril 2021
Plate-formes : Linux, Mac, Windows
Langue : Français
Référencé dans
Navigation

Simulateur de relativité restreinte

Ce script permet de visualiser l'exemple ultra classique illustrant les distorsions du temps et de l'espace en relativité restreinte :
Le wagon en déplacement par rapport à un quai.
Il suffit de lancer ce script et de jouer avec les flèches droite et gauche.
Le second lien de téléchargement semble fonctionner... (à la différence du premier)
Avatar de VinsS
Expert éminent https://www.developpez.com
Le 25/11/2015 à 7:55
Salut,

Le téléchargement ne se fait pas. Page blanche après click sur le bouton.
Avatar de Captain'Flam
Membre confirmé https://www.developpez.com
Le 25/11/2015 à 9:51

voici le script ici, à copier/coller


# encoding:utf8

''' Simulateur de relativité restreinte
==================================================

Ce script permet de visualiser l'exemple ultra classique illustrant les distorsions
du temps et de l'espace en relativité restreinte :
Le wagon en déplacement par rapport à un quai.
Il suffit de lancer ce script et de jouer avec les flèches droite et gauche.
On peut voir, sous le wagon, des horloge qui donnent l'heure "locale" à différentes positions.

Quelques explications à peu près scientifiques :

On commence par définir le référentiel ("immobile") de l’observateur : le quai.
Ensuite, dans le le référentiel du wagon qui se déplace à une vitesse V par rapport au quai,
on a un point p qui se déplace à la vitesse v, et est à la position x0 quand t = 0.
On a donc : position de p dans le référentiel du wagon = x = x0 + vt

A un instant T sur le quai, on veut connaître X, la position de p vu depuis le quai.

On utilise la transformation de Lorentz
t = γ( T - βX/c )
x = γ( X - βcT )
en remplaçant x par x0 + vt :
x0 + vt = γ( X - βcT )

On connaît x0, v et T, et on veut X et t.

x0 + vγ( T - βX/c ) = γ( X - βcT )
x0 + vγT - vγβX/c = γX - γβcT
γX + vγβX/c = x0 + γβcT + vγT
X( γ + vβγ/c ) = x0 + γβcT + vγT
X = ( x0 + γβcT + vγT ) / ( vβγ/c + γ )
X = ( x0/γ + βcT + vT ) / ( vβ/c + 1 )
X = ( x0/γ + T( v + βc )) / ( vβ/c + 1 ) <-- voici X
t = γ( T - βX/c ) <-- et t

Dans les formules qui précèdent et le code qui suit, les capitales
désignent les coordonnées dans le référentiel du quai,
et les minuscules, celles du référentiel en mouvement (le wagon).

Les variables "q" désignent des "quasi-quadri-vecteurs", c'est-à-dire,
dans ce contexte, une paire (z,t) où z donne les coordonnées
spatiales 2D sous forme d'un nombre complexe, et t le temps.
Par ailleurs, les variables "c", "b", et "g" contiennent respectivement
la vitesses de la lumière dans les unités de mesures choisies,
β = le rapport v/c, et γ = le facteur de Lorentz.

Hadrien Flammang - nov 2015
'''

def lorentz ( x0,y0,vx,vy,T,c,b,g ):
''' Variante de la transformation de Lorentz qui calcule
X,Y,t en fonction de x0,y0,vx,vy,T '''
X = ( x0/g + T*( vx + b*c )) / ( vx*b/c + 1 )
t = g*( T - b*X/c )
Y = y0 + vy*t
return X,Y,t

#-------------------------------------------------------------------
#-- quelques outils génériques -------------------------------------

iterable = lambda obj : hasattr( obj,'__iter__')
flatize = lambda obj : sum( map( flatize,obj ),[] ) if iterable( obj ) else
invcomplex = lambda z : complex( z.imag,z.real )
def to_complex ( *z ) :
try : return complex( *z )
except : pass
try : return complex( *z )
except : return 0

#-------------------------------------------------------------------
#-- Les classes des différents objets en mouvement (dans un repère qui sera donné)

nope,box,dot,clock,text = range( 5 )

class Object:
def __init__(self,type=nope,**param):
self.type = type
self.pos = to_complex( param.get('pos',0 ))
self.size = to_complex( param.get('size',0 ))
self.speed = to_complex( param.get('speed',0 ))
self.clock = param.get('clock',False )
self.text = param.get('text',None )
self.start = param.get('start',0 )
self.color = param.get('color',0 )

def draw (self,t,trans,drawer): # trans = fonction de transformation : ( x,v,T )-> (X,t) avec x,v,X complexes
if self.type == nope : return
q0 = trans( self.pos,self.speed,t )
q1 = trans( self.pos+self.size,self.speed,t )
if self.type == box : drawer.box ( q0,q1,self.color )
elif self.type == dot : drawer.dot ( q0,self.color )
elif self.type == text : drawer.text ( q0,self.text,self.color )
elif self.type == clock : drawer.clock( q0,self.color )
if self.clock : drawer.clock( (q0+1j,q0),self.color )

def Nop ( **param ) : return Object() # objet invisible et qui ne fait rien...
def Box ( **param ) : return Object( box ,**param ) # rectangle (pour symboliser un wagon)
def Dot ( **param ) : return Object( dot ,**param ) # point (pour symboliser un projectile ou un photon)
def Text ( **param ) : return Object( text ,**param ) # explication bienvenue qui accompagne un objet
def Clock ( **param ) : return Object( clock,**param ) # horloge qui donne le temps propre dans un repère

#-------------------------------------------------------------------
#-- repère défini par une position et une vitesse ------------------

class Frame:
def __init__( self,position,speed,c=1 ):
speed = to_complex( speed )
self.onx = speed.imag == 0
self.V = speed
self.O = to_complex( position )
self.v = speed.real or speed.imag
self.c = c
self.b = self.v/c
self.g = (1-self.b**2)**-0.5
assert speed.real == 0 or speed.imag == 0 # la vitesse d'un repère ne peut être que horizontale ou verticale

def __call__ (self,x0,v,T): # fonction de transformation (ici : celle de Lorentz)
O,V,b,c,g = self.O,self.V,self.b,self.c,self.g
(x0x,x0y),(vx,vy) = (x0.real,x0.imag),(v.real,v.imag)
x0,y0,v,vy = (x0x,x0y,vx,vy) if self.onx else (x0y,x0x,vy,vx)
X,Y,t = lorentz( x0,y0,vx,vy,T,self.c,self.b,self.g )
Z = complex( X,Y ) if self.onx else complex( Y,X )
return self.O+Z,t

#-------------------------------------------------------------------
#-- classe d'affichage des objets ----------------------------------

class Drawer :
def __init__(self,canvas,origin=0,scale=1): # canvas doit se comporter comme un Tkinter.canvas
self.colors = ('#000','#00b','#080','#c00')
self.canvas = canvas
self.origin = to_complex(origin)
self.scale = to_complex(scale)
self.font = ('Arial narrow',int(scale*0.8))

def _int (self,*qpoints ):
qpoints = ( q*self.scale+self.origin for q in qpoints )
qpoints = flatize( (q.real,q.imag) for q in qpoints )
return map( int,qpoints )

def box (self,q0,q1,color ):
v = self._int( q0,q1 )
self.canvas.create_rectangle( *v,width=2,outline=self.colors )

def dot (self,q,color ):
r,(x,y) = 2,self._int( q )
self.canvas.create_oval( x-r,y-r,x+r,y+r,outline=self.colors,fill=self.colors )

def text (self,q,txt,color ):
if not txt : return
(x,y) = self._int( q )
self.canvas.create_text( x,y,text=txt,font=self.font,fill=self.colors )

def clock (self,q,color ):
t,(x,y) = q,self._int( q )
self.canvas.create_text( x,y,text='%.1f'%t,font=self.font,fill=self.colors )

#-------------------------------------------------------------------

def relativity ( size,origin,scale,dT,*frames ):

def draw ( step = 0 ):
root.T += dT*step
can.delete('all')
can.create_text( size/2,size-10,text='FLÈCHES du temps , ECHAP pour quitter' )
for frame in frames :
for obj in frame[1:]:
obj.draw( root.T,frame,drawer )

import Tkinter
root = Tkinter.Tk()
root.T = 0
root.geometry('+20+20')
root.bind('' ,lambda e : draw(-1))
root.bind('' ,lambda e : draw(+1))
root.bind('' ,lambda e : draw(+5))
root.bind('',lambda e : root.quit())
can = Tkinter.Canvas( root,width = size,height = size )
can.pack()
drawer = Drawer( can,origin,scale )
draw()
root.mainloop()

#-------------------------------------------------------------------
#--- démo avec unité de temps = seconde
# unité de longueur = seconde-lumière (~300000km) => c = 1

def build_wagon ( pos,speed,nbclock,color,text,vertical_photon=False ):
''' Construit un repère contenant un wagon long de 20sl + 2 photons qui partent de son centre. '''
wsize = 20
frame = Frame( pos*1j,speed,1 )
wagon = Box( pos=-wsize/2+1j,size=wsize+4j,color=color )
spot1 = Dot( pos=3j,speed= 1,clock=True,color=color )
spot2 = Dot( pos=3j,speed=-1,clock=True,color=color )
spotV = (Dot if vertical_photon else Nop)( pos=3j,speed=1j,clock=True,color=color )
name = Text( pos=2j,text=text,color=color )
clocks = tuple(Clock( pos=i+6j,color=color ) for i in xrange( -wsize/2,wsize/2+1,wsize/(nbclock-1)))
return (frame,wagon,spot1,spot2,spotV,name)+clocks

def demo1 ( scale = 10 ):
deck = build_wagon( 0,0 ,3,0,'wagon sur le quai' )+(Box( pos=-100,size=200+8j ),)
wagon1 = build_wagon( 9,0.1,5,1,'wagon 10%' )
wagon2 = build_wagon( 16,0.8,5,2,'wagon 80%' )
wagon3 = build_wagon( 23,0.9,5,3,'wagon 90%' )
relativity( (scale*80,scale*35),(scale*20,0),scale,0.1,deck,wagon1,wagon2,wagon3 )

demo1( 20 )


Si quelqu'un sait comment rendre le script téléchargeable depuis la page d'origine...

Hadrien

Avatar de Captain'Flam
Membre confirmé https://www.developpez.com
Le 25/11/2015 à 9:56
Sinon, le deuxième lien de téléchargement semble fonctionner...
Avatar de torquemada
Membre régulier https://www.developpez.com
Le 15/12/2015 à 10:57
Bonjour,
J'ai une erreur à l'exécution
NameError: name 'xrange' is not defined
cordialement
Avatar de VinsS
Expert éminent https://www.developpez.com
Le 15/12/2015 à 12:34
Salut,

Et si tu gommes le 'x' ?
Avatar de Captain'Flam
Membre confirmé https://www.developpez.com
Le 11/03/2016 à 15:24
Pardon !
J'aurais dû préciser : ce script est écrit en python 2.7, et je ne l'ai pas testé sur d'autres versions.
Avatar de LavaPower
Membre à l'essai https://www.developpez.com
Le 14/04/2016 à 12:18

Ce code devrait marcher mais je ne sais pas s'il préserve le but premier :oops:

from tkinter import *
# encoding:utf8

''' Simulateur de relativité restreinte
==================================================

Ce script permet de visualiser l'exemple ultra classique illustrant les distorsions
du temps et de l'espace en relativité restreinte :
Le wagon en déplacement par rapport à un quai.
Il suffit de lancer ce script et de jouer avec les flèches droite et gauche.
On peut voir, sous le wagon, des horloge qui donnent l'heure "locale" à différentes positions.

Quelques explications à peu près scientifiques :

On commence par définir le référentiel ("immobile") de l’observateur : le quai.
Ensuite, dans le le référentiel du wagon qui se déplace à une vitesse V par rapport au quai,
on a un point p qui se déplace à la vitesse v, et est à la position x0 quand t = 0.
On a donc : position de p dans le référentiel du wagon = x = x0 + vt

A un instant T sur le quai, on veut connaître X, la position de p vu depuis le quai.

On utilise la transformation de Lorentz
t = γ( T - βX/c )
x = γ( X - βcT )
en remplaçant x par x0 + vt :
x0 + vt = γ( X - βcT )

On connaît x0, v et T, et on veut X et t.

x0 + vγ( T - βX/c ) = γ( X - βcT )
x0 + vγT - vγβX/c = γX - γβcT
γX + vγβX/c = x0 + γβcT + vγT
X( γ + vβγ/c ) = x0 + γβcT + vγT
X = ( x0 + γβcT + vγT ) / ( vβγ/c + γ )
X = ( x0/γ + βcT + vT ) / ( vβ/c + 1 )
X = ( x0/γ + T( v + βc )) / ( vβ/c + 1 ) <-- voici X
t = γ( T - βX/c ) <-- et t

Dans les formules qui précèdent et le code qui suit, les capitales
désignent les coordonnées dans le référentiel du quai,
et les minuscules, celles du référentiel en mouvement (le wagon).

Les variables "q" désignent des "quasi-quadri-vecteurs", c'est-à-dire,
dans ce contexte, une paire (z,t) où z donne les coordonnées
spatiales 2D sous forme d'un nombre complexe, et t le temps.
Par ailleurs, les variables "c", "b", et "g" contiennent respectivement
la vitesses de la lumière dans les unités de mesures choisies,
β = le rapport v/c, et γ = le facteur de Lorentz.

Hadrien Flammang - nov 2015
'''

def lorentz ( x0,y0,vx,vy,T,c,b,g ):
''' Variante de la transformation de Lorentz qui calcule
X,Y,t en fonction de x0,y0,vx,vy,T '''
X = ( x0/g + T*( vx + b*c )) / ( vx*b/c + 1 )
t = g*( T - b*X/c )
Y = y0 + vy*t
return X,Y,t

#-------------------------------------------------------------------
#-- quelques outils génériques -------------------------------------

iterable = lambda obj : hasattr( obj,'__iter__')
flatize = lambda obj : sum( map( flatize,obj ),[] ) if iterable( obj ) else
invcomplex = lambda z : complex( z.imag,z.real )
def to_complex ( *z ) :
try : return complex( *z )
except : pass
try : return complex( *z )
except : return 0

#-------------------------------------------------------------------
#-- Les classes des différents objets en mouvement (dans un repère qui sera donné)

nope,box,dot,clock,text = range( 5 )

class Object:
def __init__(self,type=nope,**param):
self.type = type
self.pos = to_complex( param.get('pos',0 ))
self.size = to_complex( param.get('size',0 ))
self.speed = to_complex( param.get('speed',0 ))
self.clock = param.get('clock',False )
self.text = param.get('text',None )
self.start = param.get('start',0 )
self.color = param.get('color',0 )

def draw (self,t,trans,drawer): # trans = fonction de transformation : ( x,v,T )-> (X,t) avec x,v,X complexes
if self.type == nope : return
q0 = trans( self.pos,self.speed,t )
q1 = trans( self.pos+self.size,self.speed,t )
if self.type == box : drawer.box ( q0,q1,self.color )
elif self.type == dot : drawer.dot ( q0,self.color )
elif self.type == text : drawer.text ( q0,self.text,self.color )
elif self.type == clock : drawer.clock( q0,self.color )
if self.clock : drawer.clock( (q0+1j,q0),self.color )

def Nop ( **param ) : return Object() # objet invisible et qui ne fait rien...
def Box ( **param ) : return Object( box ,**param ) # rectangle (pour symboliser un wagon)
def Dot ( **param ) : return Object( dot ,**param ) # point (pour symboliser un projectile ou un photon)
def Text ( **param ) : return Object( text ,**param ) # explication bienvenue qui accompagne un objet
def Clock ( **param ) : return Object( clock,**param ) # horloge qui donne le temps propre dans un repère

#-------------------------------------------------------------------
#-- repère défini par une position et une vitesse ------------------

class Frame:
def __init__( self,position,speed,c=1 ):
speed = to_complex( speed )
self.onx = speed.imag == 0
self.V = speed
self.O = to_complex( position )
self.v = speed.real or speed.imag
self.c = c
self.b = self.v/c
self.g = (1-self.b**2)**-0.5
assert speed.real == 0 or speed.imag == 0 # la vitesse d'un repère ne peut être que horizontale ou verticale

def __call__ (self,x0,v,T): # fonction de transformation (ici : celle de Lorentz)
O,V,b,c,g = self.O,self.V,self.b,self.c,self.g
(x0x,x0y),(vx,vy) = (x0.real,x0.imag),(v.real,v.imag)
x0,y0,v,vy = (x0x,x0y,vx,vy) if self.onx else (x0y,x0x,vy,vx)
X,Y,t = lorentz( x0,y0,vx,vy,T,self.c,self.b,self.g )
Z = complex( X,Y ) if self.onx else complex( Y,X )
return self.O+Z,t

#-------------------------------------------------------------------
#-- classe d'affichage des objets ----------------------------------

class Drawer :
def __init__(self,canvas,origin=0,scale=1): # canvas doit se comporter comme un Tkinter.canvas
self.colors = ('#000','#00b','#080','#c00')
self.canvas = canvas
self.origin = to_complex(origin)
self.scale = to_complex(scale)
self.font = ('Arial narrow',int(scale*0.8))

def _int (self,*qpoints ):
qpoints = ( q*self.scale+self.origin for q in qpoints )
qpoints = flatize( (q.real,q.imag) for q in qpoints )
return map( int,qpoints )

def box (self,q0,q1,color ):
v = self._int( q0,q1 )
self.canvas.create_rectangle( *v,width=2,outline=self.colors )

def dot (self,q,color ):
r,(x,y) = 2,self._int( q )
self.canvas.create_oval( x-r,y-r,x+r,y+r,outline=self.colors,fill=self.colors )

def text (self,q,txt,color ):
if not txt : return
(x,y) = self._int( q )
self.canvas.create_text( x,y,text=txt,font=self.font,fill=self.colors )

def clock (self,q,color ):
t,(x,y) = q,self._int( q )
self.canvas.create_text( x,y,text='%.1f'%t,font=self.font,fill=self.colors )

#-------------------------------------------------------------------

def relativity ( size,origin,scale,dT,*frames ):

def draw ( step = 0 ):
root.T += dT*step
can.delete('all')
can.create_text( size/2,size-10,text='FLÈCHES du temps , ECHAP pour quitter' )
for frame in frames :
for obj in frame[1:]:
obj.draw( root.T,frame,drawer )

root = Tk()
root.T = 0
root.geometry('+20+20')
root.bind('' ,lambda e : draw(-1))
root.bind('' ,lambda e : draw(+1))
root.bind('' ,lambda e : draw(+5))
root.bind('',lambda e : root.quit())
can = Canvas( root,width = size,height = size )
can.pack()
drawer = Drawer( can,origin,scale )
draw()
root.mainloop()

#-------------------------------------------------------------------
#--- démo avec unité de temps = seconde
# unité de longueur = seconde-lumière (~300000km) => c = 1

def build_wagon ( pos,speed,nbclock,color,text,vertical_photon=False ):
''' Construit un repère contenant un wagon long de 20sl + 2 photons qui partent de son centre. '''
wsize = 20
frame = Frame( pos*1j,speed,1 )
wagon = Box( pos=-wsize/2+1j,size=wsize+4j,color=color )
spot1 = Dot( pos=3j,speed= 1,clock=True,color=color )
spot2 = Dot( pos=3j,speed=-1,clock=True,color=color )
spotV = (Dot if vertical_photon else Nop)( pos=3j,speed=1j,clock=True,color=color )
name = Text( pos=2j,text=text,color=color )
clocks = tuple(Clock( pos=i+6j,color=color ) for i in range( int(-wsize/2),int(wsize/2+1),int(wsize/(nbclock-1))))
return (frame,wagon,spot1,spot2,spotV,name)+clocks

def demo1 ( scale = 10 ):
deck = build_wagon( 0,0 ,3,0,'wagon sur le quai' )+(Box( pos=-100,size=200+8j ),)
wagon1 = build_wagon( 9,0.1,5,1,'wagon 10%' )
wagon2 = build_wagon( 16,0.8,5,2,'wagon 80%' )
wagon3 = build_wagon( 23,0.9,5,3,'wagon 90%' )
relativity( (scale*80,scale*35),(scale*20,0),scale,0.1,deck,wagon1,wagon2,wagon3 )

demo1( 20 )

Avatar de Salyanov
Membre à l'essai https://www.developpez.com
Le 06/03/2021 à 9:48
Merci :-)
Developpez.com décline toute responsabilité quant à l'utilisation des différents éléments téléchargés.