def admitant_2d_matrix_element_bm(mesh, row_idx, col_idx, z0, k, coupling_sign): n, ns = mesh.normals[row_idx], mesh.normals[col_idx] r = mesh.centers[row_idx] corners, admittance = mesh.corners[col_idx], mesh.admittances[col_idx] singular = row_idx == col_idx if singular: element_vector = corners[1] - corners[0] length = np.sqrt(element_vector.dot(element_vector)) lk2 = length * k / 2 return ( +(z0 * admittance * np.pi * length * k / 8) * (+hankel2(0, lk2) * struve(-1, lk2) + hankel2(1, lk2) * struve(0, lk2)) - coupling_sign * fixed_quad(regularized_hypersingular_bm_part, 0, lk2)[0] / 2 + coupling_sign * 2j / (np.pi * k * length) + (1 - coupling_sign * z0 * admittance) / 2 ) else: def integral_function(rs): return ( hs_2d(ns, k, r, rs) - 1j * k * z0 * admittance * g_2d(k, r, rs) + coupling_sign * z0 * admittance * h_2d(n, k, r, rs) + coupling_sign * 1j / k * hypersingular(k, r, rs, n, ns) ) return line_integral(integral_function, corners[0], corners[1], singular)
def radimp(wf, dia): """calculatio radiation impedance for each frequency""" if not wf > 0: return 0 if dia > 0: if _rad_calc == 'NONE': return 0 # simple open end impedance else: s = dia*dia*np.pi/4.0 k = wf/_c0 x = k*dia re = _rhoc0/s*(1 - special.jn(1, x)/x*2) # 1st order bessel function. im = _rhoc0/s*special.struve(1, x)/x*2 # 1st order struve function. if _rad_calc == 'BAFFLE': zr = re + im*1j elif _rad_calc == 'PIPE': # real is about 0.5 times and imaginary is 0.7 times when without frange. zr = 0.5*re + 0.7*im*1j return zr else: return np.inf # closed end
def randFunc(x, sdev): functions = [ np.sin(x), np.cos(x), special.gammaln(x), np.sqrt(x), np.log(x), np.log10(x), special.erf(x), np.square(x), special.struve(np.random.uniform(0, 2), x), special.rgamma(x) ] index = np.random.randint(0, int(len(functions))) choice = functions[index] / max(functions[index]) choice = (choice**2)**0.5 choice *= np.random.uniform(0, 150) choice += 10 for k in range(len(x)): devSN = np.random.normal(0, sdev) choice[k] += devSN return (choice)
def G_int_sp(x_in): """Special function solution of G(x) (Coulomb integral) Defined in Eq. (17b) Mares and Chuang, J. Appl. Phys. 74, 1388 (1993) Keyword arguments: x_in -- Normalized 2|ze-zh|/lambda """ G = x_in*(sp.pi/2.0*(sps.struve(1,x_in)-sps.y1(x_in))-1) G[x_in <= 1.0E-8] = 1.0 return G
def _create_plot_component(): x = linspace(-2.0, 10.0, 100) pd = ArrayPlotData(x=x) # Create some line plots of some of the data plot = Plot(pd, padding=50, border_visible=True, overlay_border=True) plot.legend.visible = True # Extend the plot's list of drawing layers ndx = plot.draw_order.index("plot") plot.draw_order[ndx:ndx] = ["bessel", "sine", "struve"] # Draw struve for i in range(3): y_name = "struve" + str(i) pd.set_data(y_name, struve(i, x)) renderer = plot.plot(("x", y_name), color="blue", name=y_name, line_width=2)[0] renderer.draw_layer = "struve" renderer.unified_draw = True # Draw bessels for i in range(3): y_name = "bessel" + str(i) pd.set_data(y_name, jn(i, x)) renderer = plot.plot(("x", y_name), color="green", name=y_name, line_width=2)[0] renderer.draw_layer = "bessel" renderer.unified_draw = True # Draw sines for i in range(3): y_name = "sine" + str(i) pd.set_data(y_name, sin(x * (i + 1) / 1.5)) renderer = plot.plot(("x", y_name), color="red", name=y_name, line_width=2)[0] renderer.draw_layer = "sine" renderer.unified_draw = True # Attach some tools to the plot plot.tools.append(PanTool(plot)) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) return plot
def Hv_zeros(order, n): """ Calculates the first 20 zeros of the Struve function of arbitrary order :param order: order of the Struve function :param n: number of zeros returned (max 20) """ # x-vector - use only positive part, Struve functions are # even (if order is odd) or odd( if order is even) x = np.arange(0., 70., 0.0001) H = struve(order, x) xi = zero_crossings(x, H) xi[0] = 0. return xi[1:n + 1]
def keldysh_interaction(radius, radius_0, ep12): """ Keldysh Interaction. :param radius: Distance from centre :param radius_0: Scale distance corresponding to inherent screening. :param ep12: average of top and bottome dielectric constants. :return: interaction """ term_arg = (radius / radius_0) * ep12 struve_term = spec.struve(0, term_arg) bessel_term = spec.y0(term_arg) interaction = keldysh_prefactor / radius_0 * (struve_term - bessel_term) return interaction
def misc_flatspectrum_plots(self): """ Miscilanous plots for the flat spectrum paper """ self.logger.debug("Entering misc_flatspectrum_plots") # Plot piston resistance and reactance functions from scipy.special import j1, struve x = arange(0, 15, 0.001) r1 = lambda x: 1 - 2 * j1(x) / x x1 = lambda x: 2 * struve(1, x) / x plot(x, r1(x), label="$R_{1}\left(x)\\right)$") plot(x, x1(x), linestyle="--", color="black", label="$X_{1}\left(x)\\right)$") xlim([0, 13]) annotate("$R_{1}(x)$", xy=(10, r1(10)), xycoords="data", xytext=(10.5, r1(10.5) - 0.2), arrowprops=dict(arrowstyle="->")) annotate("$X_{1}(x)$", xy=(5, x1(5)), xycoords="data", xytext=(6, x1(6) + 0.2), arrowprops=dict(arrowstyle="->")) grid(True) savefig("Analysis/Images/piston_impedance_functions.eps") # Plot the piston resisance for a 100mm piston cla() a = 0.055 c = 340 p0 = 1.2250 f = arange(100, 10000, 0.01) k = 2 * pi * f / c Rr = p0 * c * pi * a ** 2 * r1(2 * k * a) normalized_Rr = 10 * log10(Rr) - 10 * log10(Rr[-1]) semilogx(f, normalized_Rr) ax = gca() ax.set_xticks([16, 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 1000, 12500]) ax.set_xticklabels([16, 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 1000, 12500]) xlim(100, 5000) for label in ax.get_xticklabels(): label.set_rotation('vertical') grid(True) subplots_adjust(left=0.15, right=0.97, top=0.97, bottom=0.15) xlabel("Frequency Hz") ylabel("dB re $R_{1}(2ka) = 1$") savefig("Analysis/Images/piston_resistance_100mm.eps")
def kernel_fn(r: float) -> float: """ Args: r: distance from center, expressed in terms of grid position Returns: value of U(r) """ alpha = 1.0 r0 = 10 # TODO Fix this value to r -> 0 if r == 0: return -2 * alpha / r0 H0 = special.yn(0, r / r0) Y0 = special.struve(0, r / r0) return alpha / r0 * (H0 - Y0)
def _create_plot_component(): x = linspace(-2.0, 10.0, 100) pd = ArrayPlotData(x = x) # Create some line plots of some of the data plot = Plot(pd, padding=50, border_visible=True, overlay_border=True) plot.legend.visible = True # Extend the plot's list of drawing layers ndx = plot.draw_order.index("plot") plot.draw_order[ndx:ndx] = ["bessel", "sine", "struve"] # Draw struve for i in range(3): y_name = "struve" + str(i) pd.set_data(y_name, struve(i, x)) renderer = plot.plot(("x", y_name), color="blue", name=y_name, line_width=2)[0] renderer.set(draw_layer = "struve", unified_draw=True) # Draw bessels for i in range(3): y_name = "bessel" + str(i) pd.set_data(y_name, jn(i,x)) renderer = plot.plot(("x", y_name), color="green", name=y_name, line_width=2)[0] renderer.set(draw_layer = "bessel", unified_draw=True) # Draw sines for i in range(3): y_name = "sine" + str(i) pd.set_data(y_name, sin(x * (i+1) / 1.5)) renderer = plot.plot(("x", y_name), color="red", name=y_name, line_width=2)[0] renderer.set(draw_layer="sine", unified_draw=True) # Attach some tools to the plot plot.tools.append(PanTool(plot)) zoom = ZoomTool(component=plot, tool_mode="box", always_on=False) plot.overlays.append(zoom) return plot
def randFunc(x,sdev): tempDM = x/np.amax(x) functions = [ special.gammaln(tempDM), np.sqrt(tempDM), np.log(tempDM), np.log10(tempDM), special.erf(tempDM), np.square(tempDM), special.struve(np.random.uniform(0,2),tempDM) #special.rgamma(x) ] randVar = np.random.uniform(0,1) combProb = 1/2 if randVar < combProb: indices = np.random.randint(0, len(functions), 2) distA = functions[indices[0]] distB = functions[indices[1]] choice = np.concatenate((distA, distB)) choice = np.random.choice(choice, size = len(tempDM), replace = False) else: indices = np.random.randint(0, int(len(functions))) choice = functions[indices] choice /= np.amax(choice) choice = (choice**2)**0.5 choice *= np.random.uniform(2, 32) choice += 8 for k in range(len(tempDM)): devSN = np.random.normal(0,sdev) choice[k] += devSN fig2 = plt.figure() ax2 = fig2.add_subplot(111) ax2.scatter(x, choice) ax2.set_title(indices) return(choice)
def true_func(x): return struve(0, x) - y0(x)
from scipy.special import struve, y0, yn from fast_interp import FunctionGenerator as FG def protect(F): def new_func(x): if isinstance(x, np.ndarray): dtype = type(F(1)) sel = x > 1e-10 out = np.zeros(x.shape, dtype=dtype) out[sel] = F(x[sel]) else: out = 0.0 if x < 1e-10 else F(x) return out return new_func H0 = FG(lambda x: struve( 0, x), 1e-10, 10) H1 = FG(lambda x: struve(-1, x), 1e-10, 10) H2 = FG(lambda x: struve(-2, x), 1e-10, 10) H3 = FG(lambda x: struve(-3, x), 1e-10, 10) Y0 = FG(lambda x: y0(x), 1e-10, 10) Y1 = FG(lambda x: yn(1, x), 1e-10, 10) Y2 = FG(lambda x: yn(2, x), 1e-10, 10) """ Test how to do biharmonic FMM using cloud of points... """ def random3(N): a1 = np.random.rand(N)-0.5 a2 = np.random.rand(N)-0.5 a3 = np.random.rand(N)-0.5
def X(x): return struve(1, x) / x
def chi(omega, r_mouth): """Reactive part of impedance""" return struve(1, omega * r_mouth) / omega / r_mouth
import numpy as np from scipy import special from matplotlib import pyplot as plt tempDM = np.linspace(0.001, 10, 10000) # X-vals to evaluate the distributions over functions = np.array([ # Possible distributions that noise can follow special.gammaln(tempDM), np.sqrt(tempDM), np.log(tempDM), -special.gammaln(tempDM), -np.sqrt(tempDM), -np.log(tempDM), special.erf(tempDM), np.square(tempDM), -special.erf(tempDM), -np.square(tempDM), special.struve(0,tempDM), special.struve(1,tempDM), special.struve(2,tempDM), -special.struve(0,tempDM), -special.struve(1,tempDM), -special.struve(2,tempDM), [np.random.uniform(0, 5)]*len(tempDM), tempDM, -tempDM, special.rgamma(tempDM) ]) def generation(numPoints, upperDM): """Randomly pick shapes for noise to follow. With probability of multiple, different, distributions (as well as their inverted counterparts) to be convolved with each other and form unpredictable shapes. Keyword arguments: numPoints -- the number of points that the noise/fake signal will have upperDM -- the highest DM for the data (w.r.t. 0), to be multiplied by the normalised plot in the end """ np.random.seed() # As random seeds are used at some points this just ensure it is reset every time convProb = 3/4 # Probability of convolution of a signal taking place
def base_gf(x): Y = y0(x) H = struve(0, x) return 0.25 * (H - Y)
def GF(x): Y = yn(1, x) S3 = struve(-3, x) S2 = struve(-2, x) return (x * (Y - S3) - 4 * S2) / x**2
def __init__(self, N, vb, cb, epsilon, r0=33.875, shift=0.5, spin_orbit=True, cutoff=np.inf): if spin_orbit: self.model = tbmodels.Model.from_wannier_files( hr_file='TB-Models/MoS2_hr.dat', wsvec_file='TB-Models/MoS2_wsvec.dat', xyz_file='TB-Models/MoS2_centres.xyz', win_file='TB-Models/MoS2.win') else: self.model = tbmodels.Model.from_wannier_files( hr_file='TB-Models/wann_hr.dat', wsvec_file='TB-Models/wann_wsvec.dat', xyz_file='TB-Models/wann_centres.xyz', win_file='TB-Models/wann.win') self.k1 = self.model.reciprocal_lattice[0] self.k2 = self.model.reciprocal_lattice[1] self.a1 = self.model.uc[0] self.a2 = self.model.uc[1] self.norb = self.model.hamilton([0., 0., 0.]).shape[0] self.cutoff = cutoff self.epsilon = epsilon # self.r0 = r0 / epsilon self.shift = shift # scissor operator self.N = N # k-points grid self.vb = vb # valence bands self.cb = cb # conduction bands self.nv = len(self.vb) self.nc = len(self.cb) self.E = np.zeros((N, N, self.norb)) self.K = np.zeros((N, N, 3)) self.D = np.zeros((N, N, self.norb, self.norb), dtype=np.complex) self.H = np.zeros((N, N, self.norb, self.norb), dtype=np.complex) for i, j in product(range(N), range(N)): self.H[i, j] = self.model.hamilton([i / N, j / N, 0]) e, d = np.linalg.eigh(self.H[i, j]) self.E[i, j] = e self.D[i, j] = d self.K[i, j] = i * self.k1 / N + j * self.k2 / N R = np.zeros((N, N, 3)) for i, j in product(range(N), range(N)): R[i, j] = self.a1 * (i - N / 2) + self.a2 * (j - N / 2) self.R = R WR = np.zeros((N, N)) VR = np.zeros((N, N)) for i, j in product(range(N), range(N)): radius = np.linalg.norm(R[i, j]) if radius != 0: WR[i, j] = Hartree * Bohr * np.pi / ( 2 * self.epsilon * self.r0) * ( struve(0, radius / self.r0) - yn(0, radius / self.r0)) VR[i, j] = Hartree * Bohr / radius else: WR[i, j] = 0 VR[i, j] = 0 WR = np.fft.fftshift(WR) self.W = np.fft.fft2(WR) / N**2 VR = np.fft.fftshift(VR) self.V = np.fft.fft2(VR) / N**2 self.gap = self.E[:, :, cb[0]] - self.E[:, :, vb[-1]] + shift self.Egap = np.min(self.gap) self.weight = np.ones((self.N, self.N)) self.weight[self.gap > (self.Egap + self.cutoff)] = 0 self.indexes = [] for kx, ky in product(range(self.N), range(self.N)): if self.weight[kx, ky] == 1: for i, j in product(self.cb, self.vb): self.indexes.append((kx, ky, i, j)) self.NH = len(self.indexes) print('Exciton Hamiltonian size: ' + str(self.NH) + ' K-space size: ' + str(int(np.sum(self.weight)))) R = np.fft.fftshift(self.R, axes=(0, 1)) HR = np.fft.ifft2(self.H, axes=(0, 1)) dx = np.fft.fft2(1j * R[:, :, 0, None, None] * HR, axes=(0, 1)) dy = np.fft.fft2(1j * R[:, :, 1, None, None] * HR, axes=(0, 1)) for i, j in product(range(N), range(N)): dx[i, j] = np.linalg.multi_dot( [self.D[i, j].T.conj(), dx[i, j], self.D[i, j]]) dy[i, j] = np.linalg.multi_dot( [self.D[i, j].T.conj(), dy[i, j], self.D[i, j]]) self.dx = dx self.dy = dy
def _init_values_struve(self): temp_values = np.arange(0, 20, 0.002) self.value_map = special.struve(1, temp_values) c_max = np.amax(self.value_map) np.multiply(self.value_map, 1.0 / c_max, out=self.value_map) self.value_map = np.concatenate((self.value_map, self.value_map[::-1]))
def G(a, gamma): if abs(gamma) < 1.0e-9: return 1.0 else: x = 2 * abs(gamma) / a return x * (np.pi / 2 * (sp.struve(1, x) - sp.y1(x)) - 1)
from mpl_toolkits.mplot3d import Axes3D from matplotlib import cm from matplotlib.ticker import LinearLocator, FormatStrFormatter import matplotlib.pyplot as plt from scipy import special import numpy as np fig = plt.figure() ax = fig.gca(projection='3d') X = np.arange(-5, 5, 0.25) Y = np.arange(-5, 5, 0.25) X, Y = np.meshgrid(X, Y) R = np.sqrt(X**2 + Y**2) Z = special.struve(0, R) surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False) ax.set_zlim(None, None) ax.zaxis.set_major_locator(LinearLocator(10)) ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f')) fig.colorbar(surf, shrink=0.5, aspect=5) plt.show()
def misc_flatspectrum_plots(self): """ Miscilanous plots for the flat spectrum paper """ self.logger.debug("Entering misc_flatspectrum_plots") # Plot piston resistance and reactance functions from scipy.special import j1, struve x = arange(0, 15, 0.001) r1 = lambda x: 1 - 2 * j1(x) / x x1 = lambda x: 2 * struve(1, x) / x plot(x, r1(x), label="$R_{1}\left(x)\\right)$") plot(x, x1(x), linestyle="--", color="black", label="$X_{1}\left(x)\\right)$") xlim([0, 13]) annotate("$R_{1}(x)$", xy=(10, r1(10)), xycoords="data", xytext=(10.5, r1(10.5) - 0.2), arrowprops=dict(arrowstyle="->")) annotate("$X_{1}(x)$", xy=(5, x1(5)), xycoords="data", xytext=(6, x1(6) + 0.2), arrowprops=dict(arrowstyle="->")) grid(True) savefig("Analysis/Images/piston_impedance_functions.eps") # Plot the piston resisance for a 100mm piston cla() a = 0.055 c = 340 p0 = 1.2250 f = arange(100, 10000, 0.01) k = 2 * pi * f / c Rr = p0 * c * pi * a**2 * r1(2 * k * a) normalized_Rr = 10 * log10(Rr) - 10 * log10(Rr[-1]) semilogx(f, normalized_Rr) ax = gca() ax.set_xticks([ 16, 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 1000, 12500 ]) ax.set_xticklabels([ 16, 20, 25, 31.5, 40, 50, 63, 80, 100, 125, 160, 200, 250, 315, 400, 500, 630, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000, 1000, 12500 ]) xlim(100, 5000) for label in ax.get_xticklabels(): label.set_rotation('vertical') grid(True) subplots_adjust(left=0.15, right=0.97, top=0.97, bottom=0.15) xlabel("Frequency Hz") ylabel("dB re $R_{1}(2ka) = 1$") savefig("Analysis/Images/piston_resistance_100mm.eps")