Commit 6a64cecb authored by Breno Rilho Lemos's avatar Breno Rilho Lemos 💬
Browse files

Add magnetic field and relativistic effects

parent 81167d01
...@@ -2,53 +2,107 @@ ...@@ -2,53 +2,107 @@
# particulas.py - Protótipo de animação de partículas # particulas.py - Protótipo de animação de partículas
# Para utilizar este script chame o blender com a opção -P e o nome do arquivo # Para utilizar este script chame o blender com a opção -P e o nome do arquivo
# #
# $ blender -P ./animate_particles.py # For console only rendering:
# $ blender -noaudio --background -P animate_particles.py
#
# TODO: - Implement command line arguments
# - https://blender.stackexchange.com/questions/6817/how-to-pass-command-line-arguments-to-a-blender-python-script
import bpy import bpy
bpy.context.user_preferences.view.show_splash = False bpy.context.user_preferences.view.show_splash = False
import math import math
import os import os
import random
# Import Particle class # Import Particle class
filename = os.path.join(os.path.basename(bpy.data.filepath), "particle.py") filename = os.path.join(os.path.basename(bpy.data.filepath), "particle.py")
exec(compile(open(filename).read(), filename, 'exec')) exec(compile(open(filename).read(), filename, 'exec'))
t_video=10 # duração da animação em segundos t_video=10 # total video duration in seconds
t_simulado=10 t_simulado=0.01 # tempo em microssegundos ~ tempo para percorrer 3m na velocidade da luz
fps = 24 # quadros por segundo fps = 24 # frames per second
N_quadros=t_video*fps # calculando numero de quadros totais N_frames=t_video*fps # Total number of frames
delta_t=t_simulado/N_quadros # tempo passado por quadro delta_t=t_simulado/N_frames # time elapsed per frame
particle_types = ["Electron","Pion","Muon","Proton","Kaon"]
clRed = (1, 0, 0)
clGreen = (0, 1, 0)
clBlue = (0, 0, 1)
clMagenta = (0.75, 0, 1)
clYellow = (1, 1, 0)
particle_colors = {"Electron":clRed, "Pion":clGreen, "Muon":clBlue, "Proton":clMagenta, "Kaon": clYellow}
# Particle radius # Particle radius
r_part = 0.10 r_part = 0.05
# Event Multiplicity
n_particles = 10
# Configure Environment
bcs = bpy.context.scene
bcs.world.light_settings.use_environment_light = False
bcs.world.light_settings.environment_energy = 0.1
# Configure Output
bcsr = bcs.render
bcsr.resolution_percentage = 50
bcsr.image_settings.file_format = 'FFMPEG'
bcsr.ffmpeg.format = "MPEG4"
bcsr.ffmpeg.codec = "H264"
bcsr.ffmpeg.use_max_b_frames = False
bcsr.ffmpeg.video_bitrate = 6000
bcsr.ffmpeg.maxrate = 9000
bcsr.ffmpeg.minrate = 0
bcsr.ffmpeg.buffersize = 224 * 8
bcsr.ffmpeg.packetsize = 2048
bcsr.ffmpeg.muxrate = 10080000
xpixels = int(bcsr.resolution_percentage * bcsr.resolution_x / 100)
output_prefix="N"+str(n_particles)+"_Gaussian_"+str(xpixels)+"px_"
bcsr.filepath = "/tmp/blender/"+output_prefix
#bcsr.threads_mode = 'FIXED'
#bcsr.threads = 16
# Function that creates Blender Objects from input list of particles. # Function that creates Blender Objects from input list of particles.
## Returns a list of blender objects ## Returns a list of blender objects
def create(particles): def create(particles):
bpy.context.scene.render.fps=fps bcsr.fps=fps
bpy.context.scene.frame_start = 0 bcs.frame_start = 0
bpy.context.scene.frame_end = N_quadros bcs.frame_end = N_frames
blender_particles=[] blender_particles=[]
#Create Materials
for type in particle_types:
bpy.data.materials.new(name=type)
#bpy.context.object.active_material = (1, 0, 0)
bpy.data.materials[type].diffuse_color = particle_colors[type]
# Create blender spheres (particles) # Create blender spheres (particles)
for particle in particles: for particle in particles:
this_type=random.choice(particle_types)
print("Adding Sphere - Particle " + str(len(blender_particles))+" of "+str(n_particles-1)+" - "+this_type)
bpy.ops.mesh.primitive_uv_sphere_add() bpy.ops.mesh.primitive_uv_sphere_add()
this_particle = bpy.context.object this_particle = bpy.context.object
this_particle.name = "part"+str(particle.iDx) this_particle.name = "part"+str(particle.iDx)
this_particle.location=((particle.x,particle.y,particle.z)) this_particle.location=((particle.x,particle.y,particle.z))
this_particle.delta_scale=(r_part,r_part,r_part) this_particle.delta_scale=(r_part,r_part,r_part)
this_particle.data.materials.clear()
this_particle.data.materials.append(bpy.data.materials[this_type])
blender_particles.append(this_particle) blender_particles.append(this_particle)
return blender_particles return blender_particles
# Function that animates the scene using the particle propagator class # Function that animates the scene using the particle propagator class
def animate(objects): def animate(objects):
#Animate particles #Animate particles
for f in range(1, N_quadros): for f in range(1, N_frames):
t=delta_t*f t=delta_t*f
bpy.context.scene.frame_current = f bcs.frame_current = f
print("Configuring Frame: "+str(f)+" of "+str(N_frames))
for i in range(0, len(objects)): for i in range(0, len(objects)):
bpy.context.scene.objects.active=objects[i] bcs.objects.active=objects[i]
objects[i].location=(particles[i].Propagate(t)) objects[i].location=(particles[i].Propagate(t))
objects[i].keyframe_insert(data_path='location') objects[i].keyframe_insert(data_path='location')
...@@ -56,18 +110,37 @@ def animate(objects): ...@@ -56,18 +110,37 @@ def animate(objects):
# Remove cube # Remove cube
bpy.data.objects.remove(bpy.data.objects['Cube']) bpy.data.objects.remove(bpy.data.objects['Cube'])
camera_forward=bpy.data.objects['Camera']
camera_forward.name = 'ForwardCamera'
camera_forward.location=(0,0,6)
camera_forward.rotation_euler[0] = 0
camera_forward.rotation_euler[2] = 0
bpy.ops.object.camera_add(location=(6, 0, 0), rotation=(0, 1.5708, 0))
#bpy.context.object.rotation_euler[1] = 1.5708
bpy.context.object.name = "BarrelCamera"
# Select scene camera
bpy.context.scene.camera = bpy.data.objects["ForwardCamera"]
# Create particles # Create particles
particles = createNparticlesProp(1000) particles = createNparticlesPropGaussian(n_particles)
# Create blender objects # Create blender objects
blender_particles = create(particles) blender_particles = create(particles)
#Animate Scene #Animate Scene
animate(blender_particles) animate(blender_particles)
bpy.context.scene.frame_current = 20
## Todo: ## Todo:
## - Lamp and cameras in suitable positions
## - Configure particle and background colors
## - Configure output format and enconding (FFmpeg & H.264 works fine)
## - Add option to keep particle trails ## - Add option to keep particle trails
## - Add simple geometry of the ALICE detector ## - Add simple geometry of the ALICE detector
## Save blender file
#bpy.ops.wm.save_as_mainfile(filepath="/home/pezzi/particles_"+str(n_particles)+".blend")
# Render animation
bpy.ops.render.render(animation=True)
#exit()
...@@ -5,7 +5,7 @@ import random ...@@ -5,7 +5,7 @@ import random
# Basic particle class to store bascic information # Basic particle class to store bascic information
class Particle: class Particle:
def __init__(self, index, x = 0, y = 0, z = 0, charge = 1, mass=1): def __init__(self, index, x = 0, y = 0, z = 0, charge = 1, mass=0.94):
self.iDx=index self.iDx=index
self.x=x self.x=x
self.y=y self.y=y
...@@ -28,26 +28,32 @@ def createNparticles(N_particles, x = 0, y = 0, z = 0): # Create particles at g ...@@ -28,26 +28,32 @@ def createNparticles(N_particles, x = 0, y = 0, z = 0): # Create particles at g
# Derived class to computes the time evolution particle positions # Derived class to computes the time evolution particle positions
class ParticlePropagator(Particle): class ParticlePropagator(Particle):
def SetMagneticField(self,B): def SetMagneticField(self, B = 0.5):
self.B = B self.B = B
def SetMomentum(self,Px, Py, Pz): def SetProperties(self, Px, Py, Pz):
self.Px = Px self.Px = Px # unit: Gev/c
self.Py = Py self.Py = Py # unit: Gev/c
self.Pz = Pz self.Pz = Pz # unit: Gev/c
def Propagate(self, time): # Todo: Add relativistic and magnetic field effects self.Velocity = 1/math.sqrt(1+self.mass*self.mass/(Px*Px+Py*Py+Pz*Pz)) # unit: []c
Xprop = self.x + time*self.Px/self.mass self.LorentzFactor = 1 / math.sqrt( 1 - self.Velocity * self.Velocity )
Yprop = self.y + time*self.Py/self.mass self.Vz = 300 * Pz / self.LorentzFactor / self.mass # unit: meters/micro seconds
Zprop = self.z + time*self.Pz/self.mass def Propagate(self, time):
Rx = self.Px / (self.charge * self.B) * 3.335641 # unit conversion to meters
Ry = self.Py / (self.charge * self.B) * 3.335641 # unit conversion to meters
omega = self.charge * self.B / ( self.LorentzFactor * self.mass ) * 89.876 # Angular frequency (unit: radians/micro seconds)
Xprop = self.x + Rx * math.sin(omega*time) - Ry * ( math.cos(omega*time) - 1 )
Yprop = self.y + Ry * math.sin(omega*time) + Rx * ( math.cos(omega*time) - 1 )
Zprop = self.z + self.Vz * time
return Xprop, Yprop, Zprop return Xprop, Yprop, Zprop
# Function that creates N particle propagators # Function that creates N particle propagators
# Momentum values to be obtained from real data # Momentum values to be obtained from real data
def createNparticlesProp(N_particles, x = 0, y = 0, z = 0): # Create particles at given position and return them in a list def createNparticlesPropGaussian(N_particles, x = 0, y = 0, z = 0): # Create particles at given position and return them in a list
particles=[] particles=[]
#loop over particles #loop over particles
for i in range(0, N_particles): for i in range(0, N_particles):
part = ParticlePropagator(i,x,y,z) part = ParticlePropagator(i,x,y,z)
part.SetMagneticField(0.5) part.SetMagneticField()
part.SetMomentum(random.gauss(0,1),random.gauss(0,1),random.gauss(0,1)) part.SetProperties(random.gauss(0,1),random.gauss(0,1),random.gauss(0,1))
particles.append(part) particles.append(part)
return particles; return particles;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment