def divergence_sphi(self,r): theta, phi = pi/2-self.xtal.gtheta, self.xtal.gphi rot_in_xtal = lambda x: Physics.rot(x, (('y', -theta), ('z', phi))) drag_in_xtal = lambda x: array(self.xtal.r) - array(x) r=rot_in_xtal(self.photon.r) r=drag_in_xtal(self.photon.r) if self.xtal.source_lens_distance == "inf": return 0.0 else: return math.atan ( r[1] / r[0] )
def generate_position(self): theta, phi = pi/2-self.xtal.gtheta, self.xtal.gphi self.photon.r = self.random_position_on_surface() # lambda functions to: # 1. Convert from the crystal reference frame to the lens reference frame; # 2. Rotate the photon WRT the lens axis till it corresponds to its defined xtal; drag_out_xtal = lambda x: array(x) + array(self.xtal.r) rot_out_xtal = lambda x: Physics.rot(x, (('y', -theta), ('z', -phi))) # Set the photon position in the observer reference frame (rotation + translation) self.photon.r=rot_out_xtal(self.photon.r) self.photon.r=drag_out_xtal(self.photon.r)
def interaction(self): """Interaction between photon and xtal.""" # Lambda function for coordinate transformation theta, phi = pi/2-self.xtal.gtheta, self.xtal.gphi drag_in_xtal = lambda x: x-self.xtal.r drag_out_xtal = lambda x: x+self.xtal.r rot_in_xtal = lambda x: Physics.rot(x, (('z', phi), ('y', theta))) rot_out_xtal = lambda x: Physics.rot(x, (('y', -theta), ('z', -phi))) in_xtal = lambda x: rot_in_xtal(drag_in_xtal(x)) out_xtal= lambda x: drag_out_xtal(rot_out_xtal(x)) # Changing reference frame for photon and xtal self.photon.k=rot_in_xtal(self.photon.k) self.photon.r = in_xtal(self.photon.r) self.xtal.g=rot_in_xtal(self.xtal.g) self.int_history=[] # History init # Photon adventure begins... while self.isinside(): interaction_type=self.which_interaction() self.interact(interaction_type) if interaction_type==0: break # Photoabsorption: the photon dies in to xtal # Photon adventure is over... if interaction_type==0: pass # Dead photon (photo-absorption) elif self.photon.knormalized[2]<=0.: # photon points towards focal plane... (no backscattering) # Back to the original reference frame self.photon.k=rot_out_xtal(self.photon.k) self.photon.r=out_xtal(self.photon.r) # transport the photon to the focal plane self.photon.travelz(0.) else: pass # Photon is backscattered and thus lost # anyway the xtal goes backs to the previous reference frame self.xtal.g=rot_out_xtal(self.xtal.g)
def divergence_stheta(self, r): source_extension = 0.035 if self.xtal.source_lens_distance == "inf": return 0.0 else: theta, phi = pi/2-self.xtal.gtheta, self.xtal.gphi rot_in_xtal = lambda x: Physics.rot(x, (('y', -theta), ('z', phi))) drag_in_xtal = lambda x: array(self.xtal.r) - array(x) r=rot_in_xtal(self.photon.r) r=drag_in_xtal(self.photon.r) if r[0] <= 0: s = math.sqrt(r[0]**2 + r[1]**2) else: s = -math.sqrt(r[0]**2 + r[1]**2) deltas = uniform (-source_extension/2 , source_extension/2 ) return math.atan(( s + deltas) / self.xtal.source_lens_distance)
def generator(self, Emin=1., Emax=1000., Exp=False, sphi=0., stheta=pi): '''Generates randomly a photon that will go on to xtal. Exp is the powerlaw spectral index (-2.1 for the Crab Nebula). ''' theta, phi = pi/2-self.xtal.gtheta, self.xtal.gphi # lambda functions # drag_out_xtal = lambda x: array(x) + array(self.xtal.r) rot_out_xtal = lambda x: Physics.rot(x, (('y', -theta), ('z', -phi))) # Puts a photon an EPSILON under the xtal surface in a random 2D point random_pos_on_surface=[uniform(-x/2., x/2.) for x in self.xtal.dim[:2]] random_pos_on_surface.append(-EPSILON) self.photon.r=random_pos_on_surface # The photon position in observer reference frame (rotation + translation) self.photon.r=rot_out_xtal(self.photon.r) self.photon.r=drag_out_xtal(self.photon.r) if self.photon.i !=1: self.photon.i=1. # wavevector definition from source angular parameters self.photon.k=Physics.makenormalvec(sphi, stheta) # Energy calculation (powerlaw if Exp is False) self.erandom((Emin, Emax), Exp=Exp)