have scatering matrix deduced

This commit is contained in:
Ryan@Home 2025-02-19 04:55:25 -05:00
parent ce95d74274
commit 6c73ed6341
4 changed files with 182 additions and 73 deletions

View File

@ -62,10 +62,26 @@ class IsotopeClass:
return [1, 'H']
if ASym == "d" :
return [2, 'H']
if ASym == "t" :
return [3, 'H']
if ASym == "h" :
return [3, 'He']
if ASym == "a" :
return [4, 'He']
match = re.match(r'(\d+)(\D+)', ASym)
return [int(match.group(1)), match.group(2) ]
def GetAZ(self, ASym : str):
if ASym == "p" :
return [1, 1]
if ASym == "d" :
return [2, 1]
if ASym == "t" :
return [3, 1]
if ASym == "h" :
return [3, 2]
if ASym == "a" :
return [3, 2]
[A, sym] = self.BreakDownName(ASym)
try:
dudu = self.data[(self.data['symbol']==sym) & (self.data['A']==A)]
@ -119,6 +135,13 @@ class IsotopeClass:
return dudu['jp'].iloc[0]
except:
return "unknown"
def GetJpi(self, A : int, Z : int):
try:
dudu = self.data[(self.data['z']==Z) & (self.data['A']==A)]
return dudu['jp'].iloc[0]
except:
return "unknown"
def GetHalfLife(self, ASym : str) -> float:
[A, sym] = self.BreakDownName(ASym)

View File

@ -1,9 +1,80 @@
#!/usr/bin/env python3
from boundState import BoundState
boundState = BoundState(16, 8, 1, 0, 0, 2, 2.5, -4.14)
boundState.SetPotential(1.10, 0.65, -6, 1.25, 0.65)
boundState.FindPotentialDepth(-70, -60, 0.5)
# boundState.PrintWF()
boundState.PlotBoundState()
from solveSE import WoodsSaxonPot, CoulombPotential, SpinOrbit_Pot, WS_SurfacePot, SolvingSE
from mpmath import coulombf, coulombg
import numpy as np
from scipy.special import gamma
# boundState = BoundState(16, 8, 1, 0, 1, 0, 0.5, -4.14)
# boundState.SetPotential(1.10, 0.65, -6, 1.25, 0.65, 1.25)
# boundState.FindPotentialDepth(-75, -60, 0.1)
# # boundState.PrintWF()
# boundState.PlotBoundState()
def SevenPointsSlope(data, n):
return (-data[n + 3] + 9 * data[n + 2] - 45 * data[n + 1] + 45 * data[n - 1] - 9 * data[n - 2] + data[n - 3]) / 60
def FivePointsSlope(data, n):
return ( data[n + 2] - 8 * data[n + 1] + 8 * data[n - 1] - data[n - 2] ) / 12
dw = SolvingSE("60Ni", "p", 30)
dw.SetRange(0, 0.1, 300)
dw.SetLJ(0, 0.5)
dw.dsolu0 = 1
dw.CalCMConstants()
dw.PrintInput()
dw.ClearPotential()
dw.AddPotential(WoodsSaxonPot(-47.937-2.853j, 1.20, 0.669), False)
dw.AddPotential(WS_SurfacePot(-6.878j, 1.28, 0.550), False)
dw.AddPotential(SpinOrbit_Pot(-5.250 + 0.162j, 1.02, 0.590), False)
dw.AddPotential(CoulombPotential(1.258), False)
rpos = dw.rpos
solU = dw.SolveByRK4()
solU /= dw.maxSolU
# for r, u in zip(rpos, solU):
# print(f"{r:.3f} {np.real(u):.6f} {np.imag(u):.6f}")
def CoulombPhaseShift(L, eta):
return np.angle(gamma(L+1+1j*eta))
sigma = CoulombPhaseShift(dw.L, dw.eta)
# find pahse shift by using the asymptotic behavior of the wave function
r1 = rpos[-2]
f1 = float(coulombf(dw.L, dw.eta, dw.k*r1))
g1 = float(coulombg(dw.L, dw.eta, dw.k*r1))
u1 = solU[-2]
r2 = rpos[-1]
f2 = float(coulombf(dw.L, dw.eta, dw.k*r2))
g2 = float(coulombg(dw.L, dw.eta, dw.k*r2))
u2 = solU[-1]
det = f2*g1 - f1*g2
A = (f2*u1 - u2*f1) / det
B = (u2*g1 - g2*u1) / det
print(f"A = {np.real(A):.6f} + {np.imag(A):.6f} I")
print(f"B = {np.real(B):.6f} + {np.imag(B):.6f} I")
ScatMatrix = (B + A * 1j)/(B - A * 1j)
print(f"Scat Matrix = {np.real(ScatMatrix):.6f} + {np.imag(ScatMatrix):.6f} I")
solU = np.array(solU, dtype=np.complex128)
solU *= np.exp(1j * sigma)/(B-A*1j)
from matplotlib import pyplot as plt
plt.plot(rpos, np.real(solU), label="Real")
plt.plot(rpos, np.imag(solU), label="Imaginary")
plt.legend()
plt.show(block=False)
input("Press Enter to continue...")

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
from solveSE import WSPotential, CoulombPotential, SpinOrbitPotential, SolvingSE
from solveSE import WoodsSaxonPot, CoulombPotential, SpinOrbit_Pot, SolvingSE
from scipy.optimize import curve_fit
from scipy.interpolate import interp1d
@ -12,22 +12,14 @@ import mpmath
mpmath.mp.dps = 15 # Decimal places of precision
def SevenPointsSlope(data, n):
return (-data[n + 3] + 9 * data[n + 2] - 45 * data[n + 1] + 45 * data[n - 1] - 9 * data[n - 2] + data[n - 3]) / 60
class BoundState(SolvingSE):
def __init__(self, A, ZA, a, Za, node, L, J, BE):
super().__init__(A, ZA, a, Za, BE)
self.Ecm = BE
self.BE = BE
self.CalCMConstants( True)
self.SetRange(0, 0.1, 300) # default range
self.PrintInput()
self.node = node # number of nodes of the wave function r > 0
self.SetLJ(L, J)
self.PrintInput()
self.node = node # number of nodes of the wave function r > 0
self.FoundBounfState = False
def SetPotential(self, r0, a0, Vso, rso, aso, rc = 0.0):
@ -38,8 +30,8 @@ class BoundState(SolvingSE):
self.aso = aso
self.rc = rc
self.ClearPotential()
self.AddPotential(WSPotential(-60, r0, a0), False) # not use mass number of a
self.AddPotential(SpinOrbitPotential(Vso, rso, aso), False) # not use mass number of a
self.AddPotential(WoodsSaxonPot(-60, r0, a0), False) # not use mass number of a
self.AddPotential(SpinOrbit_Pot(Vso, rso, aso), False) # not use mass number of a
if rc > 0 and self.Z_a > 0:
self.AddPotential(CoulombPotential(rc), False) # not use mass number of a
@ -50,8 +42,8 @@ class BoundState(SolvingSE):
maxLastSolU = 0
for V0 in V0List:
self.ClearPotential()
self.AddPotential(WSPotential(V0, self.r0, self.a0), False)
self.AddPotential(SpinOrbitPotential(self.Vso, self.rso, self.aso), False) # not use mass number of a
self.AddPotential(WoodsSaxonPot(V0, self.r0, self.a0), False)
self.AddPotential(SpinOrbit_Pot(self.Vso, self.rso, self.aso), False) # not use mass number of a
if self.rc > 0 and self.Z_a > 0:
self.AddPotential(CoulombPotential(self.rc), False)
wf = self.SolveByRK4()
@ -62,16 +54,16 @@ class BoundState(SolvingSE):
maxLastSolU = lastSolU[-1]
if minLastSolU >= 0 or maxLastSolU <= 0:
print("No bound state found in the range")
print("min Last SolU = ", minLastSolU)
print("max Last SolU = ", maxLastSolU)
plt.plot(V0List, lastSolU, marker="x")
plt.grid()
plt.xlabel('V0 (MeV)')
plt.show(block=False)
input("Press Enter to exit.")
print("No bound state found in the range")
print("min Last SolU = ", minLastSolU)
print("max Last SolU = ", maxLastSolU)
plt.plot(V0List, lastSolU, marker="x")
plt.grid()
plt.xlabel('V0 (MeV)')
plt.show(block=False)
input("Press Enter to exit.")
return
return
f = interp1d(lastSolU, V0List, kind='cubic')
self.V_BS = f(0)
@ -79,8 +71,8 @@ class BoundState(SolvingSE):
# recaluclate the wave function for V_BS
self.ClearPotential()
self.AddPotential(WSPotential(self.V_BS, self.r0, self.a0), False)
self.AddPotential(SpinOrbitPotential(self.Vso, self.rso, self.aso), False) # not use mass number of a
self.AddPotential(WoodsSaxonPot(self.V_BS, self.r0, self.a0), False)
self.AddPotential(SpinOrbit_Pot(self.Vso, self.rso, self.aso), False) # not use mass number of a
if self.rc > 0 and self.Z_a > 0:
self.AddPotential(CoulombPotential(self.rc), False)
@ -109,7 +101,7 @@ class BoundState(SolvingSE):
self.wf[1:] = self.SolU[1:] / self.rpos[1:]
self.wf[0] = self.SolU[0] # Handle the first element separately if needed
#extrapolate wf from 0.2, 0.1 to 0.0
#extrapolate wf with quadrotic from 0.2, 0.1 to 0.0
def func(x, a, b, c):
return a * x**2 + b * x + c
popt, pcov = curve_fit(func, self.rpos[1:6], self.wf[1:6])
@ -117,18 +109,15 @@ class BoundState(SolvingSE):
if isPathWhittaker:
# patch the long range function to Whittaker function
kappa = np.sqrt(2*self.mu*np.abs(self.BE))/self.hbarc
charge = self.Z
self.eta = kappa * charge * self.ee / 2 / self.BE
R = min(self.r0 * (pow(self.A_A, 1/3) + pow(self.A_a, 1/3)) + 5 * self.a0, max(self.rpos))
rIndex = self.NearestPosIndex(R)
print(f"replacing wave function with Whittaker after R : {R:5.1f}, index : {rIndex}")
if rIndex < len(self.rpos):
R = self.rpos[rIndex]
W_values = [float(whitw(-1j*self.eta, self.L + 0.5, 2*kappa * r))/(kappa * r) for r in self.rpos]
W_values = [np.real(whitw(-1j*self.eta, self.L + 0.5, 2*self.k * r))/(self.k * r) for r in self.rpos[1:]]
W_values.insert(0, 0)
self.ANC = self.wf[rIndex] / W_values[rIndex]
self.ANC = float(self.wf[rIndex] / W_values[rIndex])
print(f"ANC : {self.ANC:10.6e}")
self.wf[rIndex:] = self.ANC * np.array(W_values[rIndex:])

View File

@ -2,7 +2,7 @@
import math
import numpy as np
import re
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '../Cleopatra'))
@ -29,7 +29,7 @@ class CoulombPotential:
else:
return (self.Charge * self.ee) / (2 * self.Rc) * (3 - (x / self.Rc)**2)
class WSPotential:
class WoodsSaxonPot:
def __init__(self, V0, r0, a0) :
self.V0 = V0
self.r0 = r0
@ -45,7 +45,7 @@ class WSPotential:
def output(self, x):
return self.V0/(1 + math.exp((x-self.R0)/self.a0))
class SpinOrbitPotential:
class SpinOrbit_Pot:
def __init__(self, VSO, rSO, aSO) :
# the LS factor is put in the SolvingSE Class
self.VSO = VSO
@ -65,7 +65,7 @@ class SpinOrbitPotential:
else :
return 4*1e+19
class WSSurface:
class WS_SurfacePot:
def __init__(self, V0, r0, a0):
self.V0 = V0
self.r0 = r0
@ -80,7 +80,7 @@ class WSSurface:
def output(self, x):
exponent = (x - self.R0) / self.a0
return self.V0 * math.exp(exponent) / (1 + math.exp(exponent))**2
return 4* self.V0 * math.exp(exponent) / (1 + math.exp(exponent))**2
#========================================
class SolvingSE:
@ -109,52 +109,78 @@ class SolvingSE:
potential_List = []
def PrintInput(self):
print(f" A : ({self.A_A:3d}, {self.Z_A:3d})")
print(f" a : ({self.A_a:3d}, {self.Z_a:3d})")
print(f" Elab : {self.Energy : 10.3f} MeV")
print(f" mu : {self.mu: 10.3f} MeV/c2")
# print(f" Ecm : {self.Ecm: 10.3f} MeV")
# print(f" k : {self.k: 10.3f} MeV/c")
# print(f" eta : {self.eta: 10.3f}")
# print(f" L : {self.L}, maxL : {self.maxL}")
print(f" A : ({self.A_A:3d}, {self.Z_A:3d}), spin : {self.spin_A},")
print(f" a : ({self.A_a:3d}, {self.Z_a:3d}), spin : {self.spin_a},")
print(f" Elab : {self.Energy : 10.5f} MeV")
print(f" mu : {self.mu: 10.5f} MeV/c2")
print(f" Ecm : {self.Ecm: 10.5f} MeV")
print(f" k : {self.k: 10.5f} MeV/c")
print(f" eta : {self.eta: 10.5f}")
print(f" L : {self.L}, maxL : {self.maxL}")
print(f" dr : {self.dr} fm, nStep : {self.nStep}")
print(f"rStart : {self.rStart} fm, rMax : {self.nStep * self.dr} fm")
print(f"spin-A : {self.sA}, spin-a : {self.sa} ")
def __init__(self, A_or_SymA = None, ZA_or_Syma = None \
, a_or_ELabPerA = None, Za_or_none = None, ELabPerA_or_none = None):
if Za_or_none is None :
self.ConstructUsingSymbol(A_or_SymA, ZA_or_Syma, a_or_ELabPerA)
else:
self.ConstructUsingAZ(A_or_SymA, ZA_or_Syma, a_or_ELabPerA, Za_or_none, ELabPerA_or_none)
def __init__(self, A, ZA, a, Za, Energy):
haha = IsotopeClass()
self.mass_A = haha.GetMassFromAZ(self.A_A, self.Z_A)
self.mass_a = haha.GetMassFromAZ(self.A_a, self.Z_a)
self.spin_A = float(eval(re.sub(r'[+-]', '', haha.GetJpi(self.A_A, self.Z_A))))
self.spin_a = float(eval(re.sub(r'[+-]', '', haha.GetJpi(self.A_a, self.Z_a))))
self.S = self.spin_a
self.mu = (self.mass_A * self.mass_a)/(self.mass_A + self.mass_a)
self.Ecm = 0.0
def ConstructUsingAZ(self, A, ZA, a, Za, ELabPerA):
print(f"ConstructUsingAZ : {A}, {ZA}, {a}, {Za}, {ELabPerA}")
self.A_A = A
self.A_a = a
self.Z_A = ZA
self.Z_a = Za
self.Z = ZA * Za
self.sA = 0
self.sa = 0
self.L = 0
self.S = 0
self.J = 0
self.Energy = ELabPerA
def ConstructUsingSymbol(self, Sym_A, Sym_a, ELabPerA):
print(f"ConstructUsingSymbol : {Sym_A}, {Sym_a}, {ELabPerA}")
self.L = 0
self.S = 0
self.J = 0
haha = IsotopeClass()
self.mass_A = haha.GetMassFromAZ(self.A_A, self.Z_A)
self.mass_a = haha.GetMassFromAZ(self.A_a, self.Z_a)
self.A_A, self.Z_A = haha.GetAZ(Sym_A)
self.A_a, self.Z_a = haha.GetAZ(Sym_a)
self.Z = self.Z_A * self.Z_a
self.Energy = ELabPerA
#self.mu = (A * a)/(A + a) * self.amu
self.mu = (self.mass_A * self.mass_a)/(self.mass_A + self.mass_a)
self.Energy = Energy
# self.E_tot = math.sqrt(math.pow((a+A)*self.amu,2) + 2 * A * self.amu * eng_Lab)
# self.Ecm = self.E_tot - (a + A) * self.amu
# self.k = math.sqrt(self.mu * 2 * abs(self.Ecm)) / self.hbarc
# self.eta = self.Z * self.ee * math.sqrt( self.mu/2/self.Ecm ) / self.hbarc
def CalCMConstants(self, useELabAsEcm = False):
if useELabAsEcm:
self.E_tot = self.Energy # total energy in CM
self.Ecm = self.Energy # KE in cm
else:
self.E_tot = math.sqrt(math.pow((self.mass_a+self.mass_A),2) + 2 * self.mass_A * self.Energy)
self.Ecm = self.E_tot - (self.mass_a + self.mass_A)
self.k = math.sqrt(self.mu * 2 * abs(self.Ecm)) / self.hbarc
if self.Z == 0 :
self.eta = 0
else:
self.eta = self.Z * self.ee * self.k /2 /self.Ecm
self.maxL = int(self.k * (1.4 * (self.A_A**(1/3) + self.A_a**(1/3)) + 5))
# self.maxL = int(self.k * (1.4 * (self.A**(1/3) + self.a**(1/3)) + 3))
def SetSpin(self, sA, sa):
self.sA = sA
self.sa = sa
self.S = self.sa
# def SetA_ExSpin(self, ExA, sA ):
# self.ExA = ExA
# self.spin_A = sA
def SetLJ(self, L, J):
self.L = L
@ -234,7 +260,7 @@ class SolvingSE:
self.SolU.append(y + dy)
dSolU.append(z + dz)
if abs(self.SolU[-1]) > self.maxSolU:
if np.real(self.SolU[-1]) > self.maxSolU:
self.maxSolU = abs(self.SolU[-1])
return self.SolU