00001
00002
00003 from data import units
00004
00005 class AlphaDecay(object):
00006 '''Nuclear decay by alpha emission'''
00007
00008 def __init__(self,qvalue,parentZ=0):
00009 '''Create an alpha decay of the given qvalue, and optional
00010 parentZ (must be set eventually)'''
00011 self.qvalue = qvalue
00012 self.parentZ = parentZ
00013 return
00014
00015 def __str__(self):
00016 return 'alpha: Z=%d Q=%.4f MeV'%(self.parentZ,self.qvalue/units.MeV)
00017
00018 def energy(self):
00019 return (self.parentZ-4)/(self.parentZ*self.qvalue)
00020
00021 pass
00022
00023
00024 class BetaDecay(object):
00025 '''Nuclear decay by beta emission'''
00026
00027 def __init__(self,qvalue,parentZ):
00028 'Create a beta decay of the given qvalue and parentZ'
00029 self.qvalue = float(qvalue)
00030 self.kine = None
00031 self.doff = True
00032 self.onlyff = False
00033
00034 if parentZ < 0:
00035 self.parentZ = -parentZ
00036 self.daughterZ = self.parentZ - 1
00037 self.betaSign = +1
00038 self.endpoint = self.qvalue - 2.0*units.electron_mass_c2
00039 else:
00040 self.parentZ = parentZ
00041 self.daughterZ = self.parentZ + 1
00042 self.betaSign = -1
00043 self.endpoint = self.qvalue
00044
00045 self._normalize()
00046 return
00047 def _normalize(self):
00048 steps = 1000
00049 dx = self.endpoint/steps
00050 lo = dx/2.0
00051 self.norm = 1.0
00052 self.norm = sum([self.dnde(i*dx+lo)*dx for i in range(steps)])
00053 self.maximum = max([self.dnde(i*dx+lo) for i in range(steps)])
00054
00055 return
00056
00057 def __str__(self):
00058 pm = '+'
00059 if self.betaSign < 0: pm = '-'
00060 return 'beta%s: Z=%d(->%d) Q=%.3f MeV'%(pm,self.parentZ,self.daughterZ,self.qvalue/units.MeV)
00061
00062 def energy(self):
00063 if self.kine is None:
00064 self.kine = self.sampleEnergy()
00065 return self.kine
00066
00067 def sampleEnergy(self):
00068 from random import Random
00069 u = Random().uniform
00070 while True:
00071 T = u(0.0,self.endpoint)
00072 P = u(0.0,self.maximum)
00073 dnde = self.dnde(T)
00074 assert(type(T) is float)
00075 assert(type(P) is float)
00076 assert(type(dnde) is float)
00077 if P <= dnde: return T
00078 continue
00079 return None
00080
00081 def dnde(self,T):
00082 if T > self.endpoint: return 0.0
00083 if T < 0.0: return 0.0
00084
00085 if self.onlyff:
00086 ret = self.fermi_function(T)
00087 else:
00088 ret = self.dnde_noff(T)
00089 if self.doff: ret *= self.fermi_function(T)
00090 return ret/self.norm
00091
00092 def dnde_noff(self,T):
00093 '''Return the unormalized dN/dE at the given beta kinetic
00094 energy and ignoring nuclear Coulomb field'''
00095 import math
00096 W = self.endpoint/units.electron_mass_c2 + 1.0
00097 E = T/units.electron_mass_c2 + 1.0
00098 return math.sqrt(E**2-1.0) * (W-E)**2 * E
00099
00100 def fermi_function(self,T):
00101 "Return the unormalized Fermi function value for given kinetic energy"
00102 import math
00103 E = T/units.electron_mass_c2 + 1.0
00104 P = math.sqrt(E*E-1.0)
00105 U = -1*self.betaSign*self.daughterZ/137.0
00106 S = math.sqrt(1.0 - U*U) - 1.0
00107 Y = 2.0*math.pi*U*E/P
00108 A1 = U*U * E*E + P*P/4.0
00109 A2 = math.fabs(Y/(1.0-math.exp(-Y)))
00110 return math.pow(A1,S)*A2
00111
00112 class GammaDecay(object):
00113 '''A decay by radiating a photon.'''
00114
00115 def __init__(self,energy):
00116 self._energy = energy
00117 return
00118
00119 def energy(self): return self._energy
00120
00121 def __str__(self):
00122 from data import units
00123 return 'gamma: %.4f MeV'%(self.energy()/units.MeV)
00124
00125 pass
00126
00127
00128 def plot_64Cu():
00129
00130 bm = BetaDecay(0.5794*units.MeV,+29)
00131 print bm
00132 Tm = map(lambda x: bm.endpoint/100*(x+0.5),range(99))
00133 Sm = map(bm.dnde,Tm)
00134
00135
00136 bp = BetaDecay(1.6751*units.MeV,-29)
00137 print bp
00138 Tp = map(lambda x: bp.endpoint/100*(x+0.5),range(99))
00139 Sp = map(bp.dnde,Tp)
00140
00141
00142 import matplotlib.pyplot as plt
00143 plt.figure(1)
00144 plt.subplot(211)
00145 plt.plot(Tp,Sp,'r')
00146 plt.subplot(212)
00147 plt.plot(Tm,Sm,'b')
00148 plt.show()
00149 return (bp,bm)
00150
00151
00152 if '__main__' == __name__:
00153 plot_64Cu()