def j0zero(s): """ method that computes root number s, s = 1,2,..., of the Besselfunction J0 where zj0 is the root, using table-values, asymptotic formulae and Newton-Raphsons method. Rellative error app. 1.0e-14 to 1.0e-15 Args: s(integer): solutian array from last iteration Returns: zj0(float): root No. s of besselfunction """ sz = np.array([2.4048225557695773, 5.520078110286311, 8.653727912911012, 11.79153443901428, 14.93091770848779]) b0 = (s - 0.25)*np.pi b08 = 0.125/b0 b082 = b08**2 z0 = b0 + b08*(1. - b082*(124./3 - b082*120928./15)) if s <= 5: zj0 = sz[s - 1] elif s > 30: zj0 = z0 else: dz0 = besselj(0, z0)/besselj(1, z0) z0 = z0 + dz0 zj0 = z0 return zj0
def j0zero(s): """ method that computes root number s, s = 1,2,..., of the Besselfunction J0 where zj0 is the root, using table-values, asymptotic formulae and Newton-Raphsons method. Rellative error app. 1.0e-14 to 1.0e-15 Args: s(integer): solutian array from last iteration Returns: zj0(float): root No. s of besselfunction """ sz = np.array([ 2.4048225557695773, 5.520078110286311, 8.653727912911012, 11.79153443901428, 14.93091770848779 ]) b0 = (s - 0.25) * np.pi b08 = 0.125 / b0 b082 = b08**2 z0 = b0 + b08 * (1. - b082 * (124. / 3 - b082 * 120928. / 15)) if s <= 5: zj0 = sz[s - 1] elif s > 30: zj0 = z0 else: dz0 = besselj(0, z0) / besselj(1, z0) z0 = z0 + dz0 zj0 = z0 return zj0
def hankel_transform(wavefield, max_radius, bessel_zeros, n_zeros=0, multipool=True): n = len(wavefield) if n_zeros <= 0: n_zeros = n wavefield = wavefield.conjugate().T m1 = (numpy.abs(besselj(1, bessel_zeros[:n])) / max_radius).conjugate().T max_frequency = bessel_zeros[n] / (2 * numpy.pi * max_radius) m2 = m1 * max_radius / max_frequency f = numpy.divide(wavefield, m1) bessel_zeros_nz = bessel_zeros[0:n_zeros] bessel_zeros_n = bessel_zeros[n] f_nz = f[0:n_zeros] bessel_jn = numpy.abs(besselj(1, bessel_zeros_nz)) / (2 / bessel_zeros_n) bessel_jm = numpy.abs(besselj(1, bessel_zeros)) if multipool: args = __create_args(__N_CPU, bessel_zeros[0:n], bessel_jm[0:n], bessel_zeros_nz, bessel_zeros_n, bessel_jn, f_nz, n) p = multiprocessing.Pool(__N_CPU) result = numpy.concatenate(p.map(__calculate, args)) p.close() else: result = __v_inner_loop(bessel_zeros[0:n], bessel_jm[0:n], bessel_zeros_nz, bessel_zeros_n, bessel_jn, f_nz) result = result.conjugate().T result = numpy.multiply(result, m2) result = result.conjugate().T return result
def _compute_kernel_2d(R, shape): J = np.mgrid[[slice(-(s//2), (s+1)//2) for s in shape]] piabsJ = np.pi * np.linalg.norm(J, axis=0) Jzero = tuple(s//2 for s in shape) K_hat = (2*R)**(-1) * R**2 / (piabsJ**2 - R**2) * ( 1 + 1j*np.pi/2 * ( piabsJ * besselj(1, piabsJ) * hankel1(0, R) - R * besselj(0, piabsJ) * hankel1(1, R) ) ) K_hat[Jzero] = -1/(2*R) + 1j*np.pi/4 * hankel1(1, R) K_hat[piabsJ == R] = 1j*np.pi*R/8 * ( besselj(0, R) * hankel1(0, R) + besselj(1, R) * hankel1(1, R) ) return 2 * R * fftshift(K_hat)
def HankelAccept(wavelength, magfield, thickness, q, Iq, theta, modelname): #============================================================================== # HankelTransform with fixed circular acceptance angle (circular aperture) for Time of Flight SESANS #============================================================================== #acceptq is the q-space needed to create limited acceptance effect SElength= wavelength*magfield G = np.zeros_like(SElength, 'd') threshold=2*pi*theta/wavelength for i, SElength_i in enumerate(SElength): allq=np.linspace() #for calculating the Q-range of the scattering power integral allIq=np.linspace() # This is the model applied to the allq q-space. Needs to refference the model somehow alldq = (allq[1]-allq[0])*1e10 sigma[i]=wavelength[i]^2*thickness/2/pi*np.sum(allIq*allq*alldq) s[i]=1-exp(-sigma) dq = (q[1]-q[0])*1e10 a = (x<threshold) acceptq = a*q acceptIq = a*Iq G[i] = np.sum(besselj(0, acceptq*SElength_i)*acceptIq*acceptq*dq) # G[i]=np.sum(integral) G *= dq*1e10*2*pi P = exp(thickness*wavelength**2/(4*pi**2)*(G-G[0]))
def HankelAccept(wavelength, magfield, thickness, q, Iq, theta, modelname): #============================================================================== # HankelTransform with fixed circular acceptance angle (circular aperture) for Time of Flight SESANS #============================================================================== #acceptq is the q-space needed to create limited acceptance effect SElength = wavelength * magfield G = np.zeros_like(SElength, 'd') threshold = 2 * pi * theta / wavelength for i, SElength_i in enumerate(SElength): allq = np.linspace( ) #for calculating the Q-range of the scattering power integral allIq = np.linspace( ) # This is the model applied to the allq q-space. Needs to refference the model somehow alldq = (allq[1] - allq[0]) * 1e10 sigma[i] = wavelength[i] ^ 2 * thickness / 2 / pi * np.sum( allIq * allq * alldq) s[i] = 1 - exp(-sigma) dq = (q[1] - q[0]) * 1e10 a = (x < threshold) acceptq = a * q acceptIq = a * Iq G[i] = np.sum( besselj(0, acceptq * SElength_i) * acceptIq * acceptq * dq) # G[i]=np.sum(integral) G *= dq * 1e10 * 2 * pi P = exp(thickness * wavelength**2 / (4 * pi**2) * (G - G[0]))
def analyticSolution(r, t, eps): """ Method that calculates the analytic solution to the differential equation: dw/dt = w'' + w/r, w = w(r,t), 0 < r < 1 where t is the time. The accuracy can be controlled by changing the value of sumtol1, which depicts the relative accuracy. Args: r(float): radial coordinat t(float): time eps(float): numerical tollerance Returns: w(float): velocity, us - ur """ if r == 1: w = 0 elif r < eps and t < eps: w = 1 else: # calculate first element seperately n = 1 lam1 = j0zero(n) arg1 = r * lam1 term1 = np.exp(-t * lam1**2) * besselj( 0, arg1) / (besselj(1, lam1) * lam1**3) sum1 = term1 sumtol = 1 * 10**-8 test = 1 while test > sumtol: n = n + 1 lamn = j0zero(n) arg = r * lamn term = np.exp(-t * lamn**2) * besselj( 0, arg) / (besselj(1, lamn) * lamn**3) sum1 = sum1 + term test = np.abs(term / term1) w = 8 * sum1 return w
def compute(x, rho, omega, mu): R = 0.01 dpdx = -1 alpha = R * sqrt(rho * omega / mu) numerator = besselj(0, 1j**1.5 * alpha * x / R) denominator = besselj(0, 1j**1.5 * alpha) bracket = 1 - numerator / denominator coefficient = dpdx * 1j / (rho * omega) profile = coefficient * bracket profile = profile.real maxValue = np.amax(profile) profile = profile / maxValue return profile
def analyticSolution(r,t,eps): """ Method that calculates the analytic solution to the differential equation: dw/dt = w'' + w/r, w = w(r,t), 0 < r < 1 where t is the time. The accuracy can be controlled by changing the value of sumtol1, which depicts the relative accuracy. Args: r(float): radial coordinat t(float): time eps(float): numerical tollerance Returns: w(float): velocity, us - ur """ if r == 1: w = 0 elif r < eps and t < eps: w = 1 else: # calculate first element seperately n = 1 lam1 = j0zero(n) arg1 = r*lam1 term1 = np.exp(-t*lam1**2)*besselj(0,arg1)/(besselj(1,lam1)*lam1**3) sum1 = term1 sumtol = 1*10**-8 test = 1 while test > sumtol: n = n + 1 lamn = j0zero(n) arg = r*lamn term = np.exp(-t*lamn**2)*besselj(0,arg)/(besselj(1,lamn)*lamn**3) sum1 = sum1 + term test = np.abs(term/term1) w = 8 * sum1 return w
def __calculate(args): index_i, index_f, c, Bessel_Jn, Bessel_Jm, F, Nzeros, N = args H = numpy.full((index_f - index_i), 0j) for jj in range(index_i, index_f): C = besselj(0, c[:Nzeros] * c[jj] / c[N]) / (Bessel_Jn * Bessel_Jm[jj]) H[jj - index_i] = numpy.dot(C[:Nzeros], F[:Nzeros]) return H
def Hankel_Transform_MGS(h, R, c, Nzeros=0, multipool=True): N = len(h) if Nzeros <= 0: Nzeros = N V = c[N] / (2 * numpy.pi * R) h = h.conjugate().T m1 = (numpy.abs(besselj(1, c[0:N])) / R).conjugate().T m2 = m1 * R / V F = numpy.divide(h, m1) Bessel_Jn = numpy.abs(besselj(1, c[0:Nzeros])) / (2 / c[N]) Bessel_Jm = numpy.abs(besselj(1, c)) if multipool: args = __create_args(__N_CPU, c, Bessel_Jn, Bessel_Jm, F, Nzeros, N) p = multiprocessing.Pool(__N_CPU) H = numpy.concatenate(p.map(__calculate, args)) p.close() else: H = numpy.full(N, 0j) for jj in range(0, N): C = besselj( 0, c[0:Nzeros] * c[jj] / c[N]) / (Bessel_Jn * Bessel_Jm[jj]) H[jj] = numpy.dot(C[0:Nzeros], F[0:Nzeros]) H = H.conjugate().T H = numpy.multiply(H, m2) H = H.conjugate().T return H
def hankel(SElength, wavelength, thickness, q, Iq): r""" Compute the expected SESANS polarization for a given SANS pattern. Uses the hankel transform followed by the exponential. The values for *zz* (or spin echo length, or delta), wavelength and sample thickness should come from the dataset. $q$ should be chosen such that the oscillations in $I(q)$ are well sampled (e.g., $5 \cdot 2 \pi/d_{\max}$). *SElength* [A] is the set of $z$ points at which to compute the Hankel transform *wavelength* [m] is the wavelength of each individual point *zz* *thickness* [cm] is the sample thickness. *q* [A$^{-1}$] is the set of $q$ points at which the model has been computed. These should be equally spaced. *I* [cm$^{-1}$] is the value of the SANS model at *q* """ from sas.sascalc.data_util.nxsunit import Converter wavelength = Converter(wavelength[1])(wavelength[0], "A") thickness = Converter(thickness[1])(thickness[0], "A") Iq = Converter("1/cm")(Iq, "1/A") # All models default to inverse centimeters SElength = Converter(SElength[1])(SElength[0], "A") G = np.zeros_like(SElength, 'd') #============================================================================== # Hankel Transform method if "wavelength" is a scalar; mono-chromatic SESANS #============================================================================== for i, SElength_i in enumerate(SElength): integral = besselj(0, q * SElength_i) * Iq * q G[i] = np.sum(integral) G0 = np.sum(Iq * q) # [m^-1] step size in q, needed for integration dq = (q[1] - q[0]) # integration step, convert q into [m**-1] and 2 pi circle integration G *= dq * 2 * pi G0 = np.sum(Iq * q) * dq * 2 * np.pi P = exp(thickness * wavelength**2 / (4 * pi**2) * (G - G0)) return P
def hankel(SElength, wavelength, thickness, q, Iq): r""" Compute the expected SESANS polarization for a given SANS pattern. Uses the hankel transform followed by the exponential. The values for *zz* (or spin echo length, or delta), wavelength and sample thickness should come from the dataset. $q$ should be chosen such that the oscillations in $I(q)$ are well sampled (e.g., $5 \cdot 2 \pi/d_{\max}$). *SElength* [A] is the set of $z$ points at which to compute the Hankel transform *wavelength* [m] is the wavelength of each individual point *zz* *thickness* [cm] is the sample thickness. *q* [A$^{-1}$] is the set of $q$ points at which the model has been computed. These should be equally spaced. *I* [cm$^{-1}$] is the value of the SANS model at *q* """ from sas.sascalc.data_util.nxsunit import Converter wavelength = Converter(wavelength[1])(wavelength[0],"A") thickness = Converter(thickness[1])(thickness[0],"A") Iq = Converter("1/cm")(Iq,"1/A") # All models default to inverse centimeters SElength = Converter(SElength[1])(SElength[0],"A") G = np.zeros_like(SElength, 'd') #============================================================================== # Hankel Transform method if "wavelength" is a scalar; mono-chromatic SESANS #============================================================================== for i, SElength_i in enumerate(SElength): integral = besselj(0, q*SElength_i)*Iq*q G[i] = np.sum(integral) G0 = np.sum(Iq*q) # [m^-1] step size in q, needed for integration dq = (q[1]-q[0]) # integration step, convert q into [m**-1] and 2 pi circle integration G *= dq*2*pi G0 = np.sum(Iq*q)*dq*2*np.pi P = exp(thickness*wavelength**2/(4*pi**2)*(G-G0)) return P
def calc_ftk_svd(n_bessel, eps, pf_grid, tr_grid): all_UU = [None] * (2 * n_bessel + 1) all_SSVV = [None] * (2 * n_bessel + 1) all_rnks = np.zeros(2 * n_bessel + 1, dtype=np.int32) xnodesr = pf_grid['xnodesr'] all_delta = tr_grid['all_delta'] n_delta = tr_grid['n_delta'] n_omega = tr_grid['n_omega'] n_trans = tr_grid['n_trans'] for qp in range(-n_bessel, n_bessel + 1): J_n = besselj(qp, -all_delta[:, np.newaxis] * xnodesr[np.newaxis, :]) U, S, Vh = np.linalg.svd(J_n) ind = S > eps rnk = sum(ind) all_rnks[qp + n_bessel] = rnk all_UU[qp + n_bessel] = U[:, :rnk] all_SSVV[qp + n_bessel] = S[:rnk, np.newaxis] * Vh[:rnk, :] SSVV_big = np.concatenate(all_SSVV, axis=0) UUU = np.concatenate(all_UU, axis=1) all_omega = np.concatenate( [2 * np.pi / n_om * np.arange(n_om) for n_om in n_omega if n_om > 0]) all_qp = np.concatenate([(k - n_bessel) * np.ones(n) for k, n in enumerate(all_rnks)]) vec_omega = np.exp(1j * all_qp[np.newaxis, :] * (all_omega[:, np.newaxis] - np.pi / 2)) BigMul_left = np.zeros((sum(all_rnks), n_trans), dtype=np.complex128) cnt = 0 for kk in range(n_delta): n_om = n_omega[kk] BigMul_left[:, cnt:cnt + n_om] = (UUU[kk, :][np.newaxis, :].T * vec_omega[cnt:cnt + n_om, :].T) cnt += n_om return all_rnks, BigMul_left, SSVV_big
def pointils2(band,wave): #VERSION 2 updates for replanned optics (smaller grating footprint) gratingsizes = np.array([81., 81., 84.4, 84.4]) #make function to generate pointils. #convolution of grating function with airy function for the relevant band deltawave = 1e-6 [sigma,alpha,beta0,order,fcam] = get_geocarb_gratinginfo(band) gratingsize=gratingsizes[band] #find central wavelength cenwave = 0.5*(wave[len(wave)//2]+wave[len(wave)//2+1])#gratinglambda(sigma,alpha,beta0,m=order) #wave=np.arange(0.001*2/deltawave)*deltawave+cenwave-0.001 #compute beta angles for these wavelengths betas = betaangle(wave,sigma,alpha,m=order) #FIRST DO GRATING FUNCTION #number of illuminated grooves Ngrooves = gratingsize*1000./sigma #phase shift deltaphi = 2*np.pi*sigma/cenwave*(np.sin(betas*dtor)-np.sin(beta0*dtor)) #total phase shift across grating phi = Ngrooves*deltaphi inten = 1/Ngrooves**2*(np.sin(phi/2)/np.sin(deltaphi/2))**2 deltawave = wave-cenwave #NOW FOR AIRY FUNCTION k = 2*np.pi/cenwave ap = 75./2./2. #radius of aperture in mm (extra factor of two from descope) bx = k*ap*1000.*np.sin((betas-beta0)*dtor) #take into account that beam speed in spectral direction #has changed due to grating magnification bx = bx*np.cos(beta0*dtor)/np.cos(alpha*dtor) airy = (2*besselj(1,bx)/bx)**2 #pdb.set_trace() airy = airy/np.nanmax(airy) #diffraction limit FWHM diffFWHM = cenwave*3.2*np.sqrt(2)*np.cos(alpha*dtor)/np.cos(beta0*dtor) #POINT ILS IS CONVOLUTION OF GRATING FUNCTION WITH AIRY FUNCTION pointils = convolve1d(inten,airy, mode='constant', cval=0.0) #pdb.set_trace() pointils = pointils/pointils.max() return pointils
def _LvN_propagate(self, S, NAC, dt): nexp = 7 Heff = S - ii * NAC self._LvN_evals(Heff) R = dt * (self.e_max - self.e_min) / 2 G = dt * self.e_min X = -ii * self.dt * Heff / R c = np.full((nexp, ), 2) c[0] = 1 phi = [self.rho, np.dot(X, self.rho) - np.dot(self.rho, X)] for k in range(2, nexp): phi.append(2 * (np.dot(X, phi[k - 1]) - np.dot(phi[k - 1], X)) + phi[k - 2]) a = [np.exp(ii * (R + G)) * c[k] * besselj(k, R) for k in range(nexp)] rho_dt = np.zeros_like(self.rho) for k in range(nexp): rho_dt += a[k] * phi[k] self.rho = rho_dt
def calculateEigenPair(a, c0, f, azimuthal_m, radial_n, mode_type, sign=1): if mode_type not in {"Kelvin", "Poincare"}: raise ValueError("Unknown mode_type: '" + mode_type + "'") if sign not in {-1, 1}: raise ValueError("Invalid sign: '" + str(sign) + "'") if mode_type == 'Kelvin' and sign == 1: raise ValueError( "Invalid parameter selection. Kelvin modes with clockwise phase propagation do not exist" ) bracket_factor = 2e-2 eps = 1e-7 PoincareEqn = lambda sig: (a / np.sqrt(c0**2 / (sig**2 - f**2))) * ( (1 / azimuthal_m) * besselj(azimuthal_m - 1, a / np.sqrt(c0**2 / ( sig**2 - f**2))) / (a / np.sqrt(c0**2 / (sig**2 - f**2))) * besselj( azimuthal_m, a / np.sqrt(c0**2 / (sig**2 - f**2)))) - 1 + (f / sig) KelvinEqn = lambda sig: (a / np.sqrt(c0**2 / (f**2 - sig**2))) * ( (1 / azimuthal_m) * besseli(azimuthal_m - 1, a / np.sqrt(c0**2 / ( f**2 - sig**2))) / (a / np.sqrt(c0**2 / (f**2 - sig**2))) * besseli( azimuthal_m, a / np.sqrt(c0**2 / (f**2 - sig**2)))) - 1 + (f / sig) # Calculate sigma if mode_type == 'Poincare' and sign == 1: sig = f for n in range(0, radial_n): rt = root(PoincareEqn, method="bisect", bracket=[(1 + eps) * sig, (1 + bracket_factor) * sig]) if rt.root is None: print( "Did not find an eigenvalue in expected range for Poincare mode with n=" + str(n)) sig = rt.root elif mode_type == 'Poincare' and sign == -1: sig = -f for n in range(0, radial_n): rt = root(PoincareEqn, method="bisect", bracket=[(1 + bracket_factor) * sig, (1 + eps) * sig]) if rt.root is None: print( "Did not find an eigenvalue in expected range for Poincare mode with n=" + str(n)) sig = rt.root else: sig = -f for n in range( 0, radial_n ): # Can also restrict n's on kelvin mode using Csanady's restriction on S. rt = root(KelvinEqn, method="bisect", bracket=[(1 - eps) * sig, -eps]) if rt.root is None: print( "Did not find an eigenvalue in expected range for Kelvin mode with n=" + str(n)) sig = rt.root Theta = lambda theta: np.exp(1j * azimuthal_m * theta) if mode_type == "Kelvin": R = lambda r: besseli(azimuthal_m, np.sqrt((f**2 - sig**2) / c0**2) * r) else: #Poincare R = lambda r: besselj(azimuthal_m, np.sqrt((sig**2 - f**2) / c0**2) * r) eigenfunction = lambda r, theta: R(r) * Theta(theta) return (sig, (lambda r, theta: eigenfunction(r, theta)))
def find_boundary_data(f, dt, xbdy, ybdy, ν, J, κ, M, k_i, k_e): ''' Computes u and du/dv on the boundary by solving the BIE system Attributes ====== kernel of the double layer, L kernel of the single layer, M solution on the boundary, u normal derivative on the boundary, dvu ''' E_C = 0.5772156649015328606065120900824; # Euler's constant N = M / 2; m = np.arange(1, N); k_ratio = k_e/k_i # Create array for ifft... a = [0] a.extend(1/m) a.append(1/N) a.extend((1/m)[::-1]) Rj = -2 * np.pi * np.fft.ifft(a); R = np.real(toeplitz(Rj, Rj)); # Prepare arrays for solving integral equation of the boundary (Kress pt. 2) L_e = np.zeros((M, M), dtype=complex); M_e = np.zeros((M, M), dtype=complex); L_i = np.zeros((M, M), dtype=complex); M_i = np.zeros((M, M), dtype=complex); L1_e = np.zeros((M, M), dtype=complex); L2_e = np.zeros((M, M), dtype=complex); M1_e = np.zeros((M, M), dtype=complex); M2_e = np.zeros((M, M), dtype=complex); L1_i = np.zeros((M, M), dtype=complex); L2_i = np.zeros((M, M), dtype=complex); M1_i = np.zeros((M, M), dtype=complex); M2_i = np.zeros((M, M), dtype=complex); A = np.zeros((2*M, 2*M), dtype=complex); F = np.zeros(2*M, dtype=complex); for m in range(0, M): for n in range(0, M): rdiff = np.asarray([xbdy[m] - xbdy[n], ybdy[m] - ybdy[n]]); distance = sqrt(np.power(rdiff[:][0], 2) + np.power(rdiff[:][1], 2)); M1_e[m][n] = -0.5 / np.pi * J[n] * besselj(0, k_e * distance); M1_i[m][n] = -0.5 / np.pi * J[n] * besselj(0, k_i * distance); if m == n: #Implementration of the Kress Quadrature L1_e[m][n] = 0; L2_e[m][n] = 0.5 / np.pi * κ[n] * J[n]; M2_e[m][n] = J[n] * ( 0.5 * 1j - E_C / np.pi - 0.5 / np.pi * np.log( 0.25 * np.power(k_e, 2) * np.power(J[n], 2))); L1_i[m][n] = 0; L2_i[m][n] = 0.5 / np.pi * κ[n] * J[n]; M2_i[m][n] = J[n] * ( 0.5 * 1j - E_C / np.pi - 0.5 / np.pi * np.log( 0.25 * np.power(k_i, 2) * np.power(J[n], 2))); else: #Compute cosθ and logterm for kernel calculation a = np.asmatrix([ν[0][n], ν[1][n]]); b = np.asmatrix(rdiff/distance); cosθ = np.asscalar(np.matmul(a, b.transpose())); logterm = log(float(4 * np.power(sin(0.5 * (m - n) * dt), 2))); #Compute kernels for the BIE system L1_e[m][n] = 0.5 * k_e / np.pi * J[n] * cosθ * besselj(1, k_e * distance); L2_e[m][n] = 0.5 * 1j * k_e * J[n] * cosθ * hankel1(1, k_e * distance) - L1_e[m][n] * logterm; M2_e[m][n] = 0.5 * 1j * J[n] * hankel1(0, k_e * distance) - M1_e[m][n] * logterm; L1_i[m][n] = 0.5 * k_i / np.pi * J[n] * cosθ * besselj(1, k_i * distance); L2_i[m][n] = 0.5 * 1j * k_i * J[n] * cosθ * hankel1(1, k_i * distance) - L1_i[m][n] * logterm; M2_i[m][n] = 0.5 * 1j * J[n] * hankel1(0, k_i * distance) - M1_i[m][n] * logterm; L_e[m][n] = 0.5 * R[m][n] * (L1_e[m][n]) + 0.5 * (np.pi / N) * (L2_e[m][n]); M_e[m][n] = (0.5 * R[m][n] * (M1_e[m][n]) + 0.5 * (np.pi / N) * (M2_e[m][n])); L_i[m][n] = 0.5 * R[m][n] * (L1_i[m][n]) + 0.5 * (np.pi / N) * (L2_i[m][n]); M_i[m][n] = 0.5 * R[m][n] * (M1_i[m][n]) + 0.5 * (np.pi / N) * (M2_i[m][n]);
def find_boundary_data(f, B, M, k_i, k_e): ''' Computes the boundary data (trace u and normal derivative dvu) by solving the BIE system using Kress quadrature: (I/2 - De) u + (k_e/k_i Se) dvu = f (I/2 + Di) u - Si dvu = 0 Parameters ========== f: source (array) B: boundary, lambdified (class) M: number of quadrature points on the boundary (even integer) k_i: wavenumber interior domain (complex number) k_e: wavenumber exterior domain (complex number) Returns ========== u: solution on the boundary (array) dvu: normal derivative of the solution on the boundary (array) ''' #Define the boundary features dt = 2.0 * np.pi / (M) θ = np.arange(0, 2 * np.pi, dt) x = B.y_l(θ)[0][:] y = B.y_l(θ)[1][:] ν = B.ν_l(θ) J = B.J_l(θ) κ = B.κ_l(θ) #Define other parameters k_ratio = k_e / k_i E_C = np.euler_gamma # Euler's constant N = M / 2 m = np.arange(1, N) # Create array for ifft a = [0] a.extend(1 / m) a.append(1 / N) a.extend((1 / m)[::-1]) Rj = -2 * np.pi * np.fft.ifft(a) R = np.real(toeplitz(Rj, Rj)) # Prepare arrays for solving integral equation of the boundary (Kress pt. 2) A = np.zeros((2 * M, 2 * M), dtype=complex) F = np.zeros(2 * M, dtype=complex) cosθ_mn = np.zeros((M, M), dtype=complex) logterm_mn = np.zeros((M, M), dtype=complex) besselj_0e_mn = np.zeros((M, M), dtype=complex) besselj_1e_mn = np.zeros((M, M), dtype=complex) hankel1_0e_mn = np.zeros((M, M), dtype=complex) hankel1_1e_mn = np.zeros((M, M), dtype=complex) besselj_0i_mn = np.zeros((M, M), dtype=complex) besselj_1i_mn = np.zeros((M, M), dtype=complex) hankel1_0i_mn = np.zeros((M, M), dtype=complex) hankel1_1i_mn = np.zeros((M, M), dtype=complex) logterm_o = {} for i in range(-M, M): if i != 0: logterm_o[i] = log(float(4 * np.power(np.sin(0.5 * i * dt), 2))) for m in range(0, M): for n in range(0, M): rdiff = np.asarray([x[m] - x[n], y[m] - y[n]]) r_distance = sqrt(rdiff[:][0]**2 + rdiff[:][1]**2) besselj_0e_mn[m, n] = besselj(0, k_e * r_distance) besselj_0i_mn[m, n] = besselj(0, k_i * r_distance) if m != n: cosθ_mn[m, n] = ν[0][n] * (rdiff[0] / r_distance) + ν[1][n] * ( rdiff[1] / r_distance) logterm_mn[m, n] = logterm_o[m - n] besselj_1e_mn[m, n] = besselj(1, k_e * r_distance) hankel1_1e_mn[m, n] = hankel1(1, k_e * r_distance) hankel1_0e_mn[m, n] = hankel1(0, k_e * r_distance) besselj_1i_mn[m, n] = besselj(1, k_i * r_distance) hankel1_1i_mn[m, n] = hankel1(1, k_i * r_distance) hankel1_0i_mn[m, n] = hankel1(0, k_i * r_distance) #Compute kernels of exterior of boundary L1_e = 0.5 * k_e / np.pi * J * cosθ_mn * besselj_1e_mn L2_e = 0.5 * 1j * k_e * J * cosθ_mn * hankel1_1e_mn - L1_e * logterm_mn M1_e = -0.5 / np.pi * J * besselj_0e_mn M2_e = 0.5 * 1j * J * hankel1_0e_mn - M1_e * logterm_mn # Usage of Kress Quadrature diag = np.arange(0, M) M2_e[diag, diag] = J * (0.5 * 1j - E_C / np.pi - 0.5 / np.pi * np.log(0.25 * (k_e**2) * (J**2))) L1_e[diag, diag] = 0 L2_e[diag, diag] = 0.5 / np.pi * κ * J L_e = 0.5 * R * L1_e + 0.5 * (np.pi / N) * L2_e M_e = 0.5 * R * M1_e + 0.5 * (np.pi / N) * M2_e #Calculate kernels of interior of boundary L1_i = 0.5 * k_i / np.pi * J * cosθ_mn * besselj_1i_mn L2_i = 0.5 * 1j * k_i * J * cosθ_mn * hankel1_1i_mn - L1_i * logterm_mn M1_i = -0.5 / np.pi * J * besselj_0i_mn M2_i = 0.5 * 1j * J * hankel1_0i_mn - M1_i * logterm_mn #Replace diagonals where m=n with exception cases L1_i[diag, diag] = 0 L2_i[diag, diag] = 0.5 / np.pi * κ * J M2_i[diag, diag] = J * (0.5j - E_C / np.pi - 0.5 / np.pi * np.log(0.25 * (k_i**2) * (J**2))) L_i = 0.5 * R * L1_i + 0.5 * (np.pi / N) * L2_i M_i = 0.5 * R * M1_i + 0.5 * (np.pi / N) * M2_i #Matrix of combined representation formulas A11 = 0.5 * np.identity(M) - L_e A12 = k_ratio * M_e A21 = 0.5 * np.identity(M) + L_i A22 = -M_i #Combine A's into one matrix, A A[0:M, 0:M] = A11 A[0:M, M:2 * M] = A12 A[M:2 * M, 0:M] = A21 A[M:2 * M, M:2 * M] = A22 #Make matrix for f and 0's, call it F F[0:M] = f #Solve for u and dvu from AU = F U = np.linalg.solve(A, F) u = U[0:M] dvu = U[M:2 * M] return u, dvu
def fanNoise(self, S, theta, Thrust, power_Watts): """ Inputs 1.S - distance from observer location to noise source [m] 2.theta - angle from thrust direction to observer location [rad] 2.Thrust - thrust [N] 3.power_watts - power in watts, from a SINGLE rotor Calculates and stores: spl - Sound pressure level in dB """ NtoLb = 0.224809 # Newtons to lb WtoHp = 0.00134102 # Watts to hp # m2f = 1.0/0.3048 # meters to feet Pref = 0.0002 # dynes/cm^2 k = 6.1e-27 # proportionality constant # Average blade CL CL = 6 * self.ctsigma # Ct / geom.solidity # Thrust in pounds T_lb = Thrust * NtoLb # Parameters VTip = self.tipspeed # tip speed, m/s S_ft = S * m2f # Distance to source in ft R_ft = self.radius * m2f # Radius in ft A_ft2 = self.area * m2f * m2f # Disc area in ft^2 P_Hp = power_Watts * WtoHp # Power in Hp M_t = VTip / self.ainf # tip mach number A_b = A_ft2 * self.solidity # blade area, sq. ft # print(self.power*0.001) # print(self.solidity) # print(S_ft, R_ft, A_ft2, P_Hp, M_t, A_b) # quit() # Compute rotational noise m_max = 10 # Maximum harmonic number p_m = numpy.zeros(m_max) for m in range(1, m_max + 1): p_m[m-1] = 169.3 * m * self.nblade * R_ft * M_t / (S_ft * A_ft2) * \ (0.76 * P_Hp / M_t**2 - T_lb * cos(theta)) * \ besselj(m * self.nblade, 0.8 * M_t * m * self.nblade * sin(theta)) # Compute total RMS sound pressure level in dynes/cm^2 = 0.1 Pa p = numpy.sqrt(numpy.sum(numpy.square(p_m))) # Convert to SPL in dB's SPL_rotational = 20 * numpy.log10(p / Pref) # Vortex Noise (pg. 11) # SPL = 10 * log(k * A_b * V_0.7^6 / 10^-16) + 20 * log(CL/0.4) [dB at 300 ft] # where # k = constant of proportionality = 6.1e-27 # k/1e-16 = 6.1e-11 # A_b = propeller blade area [ft^2] # V_0.7 = velocity at 0.7 * radius # SPL_vortex = 10 * log10(k * A_b * (0.7 * VTip)**6 / 1e-16) + 20 * log10(CL / 0.4) SPL_vortex = 10 * log10(6.1e-11 * A_b * (0.7 * VTip)**6) + 20 * log10(CL / 0.4) # Total noise # Adding atmospheric attenuation of 6 dB for every doubling of distance from reference spl = 10 * log10(10**(SPL_rotational / 10) + 10** (SPL_vortex / 10)) - 6 * log2(S_ft / 300) return spl
def getlhs(W,M): return M # define the PDE pde = pde.Parabolic(NComponents = 2, Mesh = mesh, StiffMat = a.globalStiffMat, MassMat = a.globalMassMat) pde.setNeumannFunc = gNeumann pde.setSrcFunc = fsrc pde.AssembBlockStiffMat = makeBlockMat pde.AssembBlockMassMat = makeBlockMat pde.AssembLHS = getlhs import linsolv W_free = makeBlockMat(pde.getFreeNodeArray(W)) # initial condition (bessel perturbation) #J_m (k_mn * r) * Cos(theta) written in cartesian co-ordinates f0 = [lambda p: c_10 + 0.03*c_10 * besselj(m, k_mn * np.sqrt(p[0]**2 + p[1]**2)) * p[0]/(1e-4 + np.sqrt(p[0]**2 + p[1]**2)), lambda p: c_20 + 0.03*c_20 * besselj(m, k_mn * np.sqrt(p[0]**2 + p[1]**2)) * p[0]/(1e-4 + np.sqrt(p[0]**2 + p[1]**2))] u0 = np.zeros([mesh.NumNodes,2]) for i, node in enumerate(mesh.Nodes): u0[i,0] = f0[0](node) u0[i,1] = f0[1](node) # start time loop np.savetxt(outfile_fmt % 0, u0) dt = 1e-4 print "dt = ", dt print "Mesh size = ", mesh.Diam raw_input('Press any key to start time loop')
def __inner_loop_single_iteration(bessel_zeros_jj, bessel_jm_jj, bessel_zeros_nz, bessel_zeros_n, bessel_jn, f_nz): return numpy.dot(besselj(0, bessel_zeros_nz * bessel_zeros_jj / bessel_zeros_n) / (bessel_jn * bessel_jm_jj), f_nz)
clf() subplot(211) # plot the SANS calculation plot(q, I, 'k') loglog(q, I) xlim([0.01, 1]) ylim([1, 1e9]) xlabel(r'$Q [nm^{-1}]$') ylabel(r'$d\Sigma/d\Omega [m^{-1}]$') # Hankel transform to nice range for plot nz = 61 zz = linspace(0, 240, nz) # [nm], should be less than reciprocal from q G = zeros(nz) for i in range(len(zz)): integr = besselj(0, q * zz[i]) * I * q G[i] = sum(integr) G = G * dq * 1e9 * 2 * pi # integr step, conver q into [m**-1] and 2 pi circle integr # plot(zz,G); stt = th * Lambda**2 / 4 / pi / pi * G[ 0] # scattering power according to SANS formalism PP = exp(th * Lambda**2 / 4 / pi / pi * (G - G[0])) subplot(212) plot(zz, PP, 'k', label="Hankel transform") # Hankel transform 1D xlabel('spin-echo length [nm]') ylabel('polarisation normalised') hold(True) # Cosine transformation of 2D scattering patern
opts = dict() # -------------------------------------------------------------------------- # find phase factors opts["criteria"] = criteria max_order = ceil(1.4 * tau + np.log(1e14)) if np.mod(max_order, 2) == 1: max_order -= 1 # -------------------------------------------------------------------------- # even part coeff = np.zeros((max_order // 2 + 1, 1)) for i in range(len(coeff)): coeff[i] = (-1)**(i) * besselj(2 * i, tau) coeff[0] /= 2 [phi1, out1] = QSP_Solver(coeff, 0, opts) print("- Info: \t\tQSP phase factors --- solved by L-BFGS\n") print("- Parity: \t\t%s\n- Degree: \t\t%d\n", "even", max_order) print("- Iteration times: \t%d\n", out1["iter"]) print("- CPU time: \t%.1f s\n", out1["time"]) #-------------------------------------------------------------------------- # odd part coeff = np.zeros((max_order / 2 + 1, 1)) for i in range(len(coeff)): coeff[i] = (-1)**(i) * besselj(2 * i + 1, tau)
clf() subplot(211) # plot the SANS calculation plot(q,I,'k') loglog(q,I) xlim([0.01, 1]) ylim([1, 1e9]) xlabel(r'$Q [nm^{-1}]$') ylabel(r'$d\Sigma/d\Omega [m^{-1}]$') # Hankel transform to nice range for plot nz=61; zz=linspace(0,240,nz); # [nm], should be less than reciprocal from q G=zeros(nz); for i in range(len(zz)): integr=besselj(0,q*zz[i])*I*q; G[i]=sum(integr); G=G*dq*1e9*2*pi; # integr step, conver q into [m**-1] and 2 pi circle integr # plot(zz,G); stt= th*Lambda**2/4/pi/pi*G[0] # scattering power according to SANS formalism PP=exp(th*Lambda**2/4/pi/pi*(G-G[0])); subplot(212) plot(zz,PP,'k',label="Hankel transform") # Hankel transform 1D xlabel('spin-echo length [nm]') ylabel('polarisation normalised') hold(True) # Cosine transformation of 2D scattering patern if False: qy,qz = meshgrid(q,q)
def compute_oof(self, array, radii): array = array.astype(np.double) shape = array.shape output = np.zeros(shape) self.check_normalization(radii) imgfft = fft(array) x, y, z, sphere_radius = get_min_sphere_radius(shape, self.spacing) for radius in tqdm(radii): tqdm.write(f'Computing radius {radius:.3f}...') circle = circle_length(radius) nu = 1.5 z = circle * EPSILON bessel = besselj(nu, z) / EPSILON**(3 / 2) base = radius / np.sqrt(2 * radius * self.sigma - self.sigma**2) exponent = self.normalization_type volume = get_sphere_volume(radius) normalization = volume / bessel / radius**2 * base**exponent exponent = -self.sigma**2 * 2 * np.pi**2 * sphere_radius**2 num = normalization * np.exp(exponent) den = sphere_radius**(3 / 2) besselj_buffer = num / den cs = circle * sphere_radius a = np.sin(cs) / cs - np.cos(cs) b = np.sqrt(1 / (np.pi**2 * radius * sphere_radius)) besselj_buffer = besselj_buffer * a * b * imgfft outputfeature_11 = np.real(ifft(x * x * besselj_buffer)) outputfeature_12 = np.real(ifft(x * y * besselj_buffer)) outputfeature_13 = np.real(ifft(x * z * besselj_buffer)) outputfeature_22 = np.real(ifft(y * y * besselj_buffer)) outputfeature_23 = np.real(ifft(y * z * besselj_buffer)) outputfeature_33 = np.real(ifft(z * z * besselj_buffer)) eigenvalues = eigenvalue_field33( outputfeature_11, outputfeature_12, outputfeature_13, outputfeature_22, outputfeature_23, outputfeature_33) lambda_1, lambda_2, lambda_3 = eigenvalues maxe = np.copy(lambda_1) mine = np.copy(lambda_1) mide = maxe + lambda_2 + lambda_3 if self.use_absolute: maxe[np.abs(lambda_2) > np.abs(maxe)] = lambda_2[ np.abs(lambda_2) > np.abs(maxe)] mine[np.abs(lambda_2) < np.abs(mine)] = lambda_2[ np.abs(lambda_2) < np.abs(mine)] maxe[np.abs(lambda_3) > np.abs(maxe)] = lambda_3[ np.abs(lambda_3) > np.abs(maxe)] mine[np.abs(lambda_3) < np.abs(mine)] = lambda_3[ np.abs(lambda_3) < np.abs(mine)] else: maxe[lambda_2 > np.abs(maxe)] = lambda_2[ lambda_2 > np.abs(maxe)] mine[lambda_2 < np.abs(mine)] = lambda_2[ lambda_2 < np.abs(mine)] maxe[lambda_3 > np.abs(maxe)] = lambda_3[ lambda_3 > np.abs(maxe)] mine[lambda_3 < np.abs(mine)] = lambda_3[ lambda_3 < np.abs(mine)] mide -= maxe + mine if self.response_type == 0: tmpfeature = maxe elif self.response_type == 1: tmpfeature = maxe + mide elif self.response_type == 2: tmpfeature = np.sqrt(np.maximum(0, maxe * mide)) elif self.response_type == 3: tmpfeature = np.sqrt( np.maximum(0, maxe * mide) * np.maximum(0, mide)) elif self.response_type == 4: tmpfeature = np.maximum(0, maxe) elif self.response_type == 5: tmpfeature = np.maximum(0, maxe + mide) stronger_response = np.abs(tmpfeature) > np.abs(output) output[stronger_response] = tmpfeature[stronger_response] return output
else: dia = float(input('Diameter of driver in mm : ')) f = float(input('Frequency of interested in Hz : ')) # c = 345.0 rho_a = 1.2 phi = arange(-1 * pi / 2.0, pi / 2.0 + pi / 1800.0, pi / 1800.0) phi = phi[ 1: 1800] # Is this a bug? it's shifted to the right, past the end of the array. # a = dia / 1000.0 theta = arange(pi / 1800.0, pi, pi / 1800.0) k = (2 * pi * f) / c # dir = 2 * divide(besselj(k * a, sin(theta)), (k * a * sin(theta))) # p = divide(dir, max(dir)) q = 20.0 * log10(p) # #p_s=[phi' p']; q_s = (transpose(phi), transpose(q)) # #Dirplot(q_s(:,1)*180/pi,q_s(:,2),'r-',[0 -30 5]); ax = plt.subplot('111', projection='polar') ax.plot(q_s[0], q_s[1], 'r-') ax.set_rticks(range(-30, 1, 6)) ax.set_theta_offset(pi / 2.0) ax.set_thetalim(thetamin=90, thetamax=-90) ax.set_theta_direction(-1)