def term1(self, expr, s, t, **kwargs): const, expr = factor_const(expr, s) if isinstance(expr, AppliedUndef): # Handle V(s), 3 * V(s) etc. If causal is True it is assumed # that the unknown functions are causal. result = self.func(expr, s, t) return result * const, Zero if expr.has(AppliedUndef): return const * self.product(expr, s, t, **kwargs), Zero try: # This is the common case. cresult, uresult = self.ratfun(expr, s, t, **kwargs) return const * cresult, const * uresult except: pass if expr.is_Pow and expr.args[1] == -1 and expr.args[0].is_Function: arg = expr.args[0].args[0] m = self.dummy_var(expr, 'm', level=0, real=True) if expr.args[0].func == sym.cosh: scale, shift = scale_shift(arg, s) if shift == 0: return const * 2 * sym.Sum( (-1)**m * sym.DiracDelta(t - scale * (2 * m + 1)), (m, 0, sym.oo)), Zero elif expr.args[0].func == sym.sinh: scale, shift = scale_shift(arg, s) if shift == 0: return const * 2 * sym.Sum( sym.DiracDelta(t - scale * (2 * m + 1)), (m, 0, sym.oo)), Zero elif expr.args[0].func == sym.tanh: scale, shift = scale_shift(arg, s) if shift == 0: return const * 2 * sym.Sum( (-1)**m * sym.DiracDelta(t - scale * (2 * m + 1)), (m, 1, sym.oo)) + const * sym.DiracDelta(t), Zero if expr.has(sym.cosh) and expr.has(sym.sinh): try: return const * self.tline_end(expr, s, t), Zero except: pass try: return const * self.tline_start(expr, s, t), Zero except: pass if expr.is_Pow and expr.args[0] == s: return Zero, const * self.power(expr, s, t) self.error('Cannot determine inverse Laplace transform')
def generate_cross_section(N, arg, atom_list): """Generates the Cross-Section Formula for the one magnon case""" S = sp.Symbol('S', commutative=True) gam = sp.Symbol('gamma', commutative=True) r = sp.Symbol('r0', commutative=True) h = sp.Symbol('hbar', commutative=True) k = sp.Symbol('k', commutative=True) kp = sp.Symbol('kp', commutative=True) g = sp.Symbol('g', commutative=True) F = sp.Function('F') kap = sp.Symbol('kappa', commutative=True) kapx = sp.Symbol('kappax', commutative=True) kapy = sp.Symbol('kappay', commutative=True) w = sp.Symbol('w', commutative=True) W = sp.Symbol('W', commutative=False) t = sp.Symbol('t', commutative=True) dif = sp.Symbol('diff', commutative=False) A = sp.Wild('A', exclude=[0]) B = sp.Wild('B', exclude=[0]) C = sp.Wild('C', exclude=[0]) D = sp.Wild('D', exclude=[0]) front_constant = (gam * r)**2 / (2 * pi * h) * (kp / k) * N front_func = (1. / 2.) * g * F(kap) * exp(-2 * W) temp2 = [] temp3 = [] temp4 = [] # This is were the heart of the calculation comes in. # First the exponentials are turned into delta functions: # exp(I(wq*t - w*t)) ---> delta(wq-w) # exp(I(wq*t - w*t)+I*(q-qp)*l) ---> delta(wq*t-w*t+q*l-qp*l) ---> delta(wq-w)*delta(q*l-qp*l) # NEEDS REVIEW for i in range(len(arg)): # _ for j in range(N): # ^ arg[i][j] = (arg[i][j] * exp(-I * w * t)).expand() # | arg[i][j] = sub_in(arg[i][j], exp(A * I * t + B * I * t), sp.DiracDelta(A + B)) # | arg[i][j] = sub_in(arg[i][j], exp(I * t * A + I * t * B + I * C + I * D), sp.DiracDelta(A * t + B * t + C + D)) # | arg[i][j] = sub_in(arg[i][j], sp.DiracDelta(A * t + B * t + C + D), sp.DiracDelta(A + B) * sp.DiracDelta(C + D)) # | temp2.append(exp(I * kap * atom_list[j]) * arg[i][j]) # | temp3.append(sum(temp2)) # | print "Converted to Delta Functions!" # | for i in range(len(temp3)): # | temp4.append((1 - kapx**2) * temp3[i]) # V dif = front_constant * front_func**2 * (sum(temp4)) # _ print "Cross-section calculated!" return dif
def __build_energy_distribution_function(energy_distribution_function, energy_spread): conduction_band_energy, energy, trap_central_energy_level = sym.symbols( 'Ecb E Et') if energy_distribution_function in energy_distribution_functions[ 'Single Level']: energy_distribution = sym.DiracDelta(energy - conduction_band_energy + trap_central_energy_level) elif energy_distribution_function in energy_distribution_functions[ 'Gaussian Level']: energy_distribution = sym.exp( -((energy - conduction_band_energy + trap_central_energy_level) **2) / (2 * energy_spread**2)) energy_distribution /= (sym.sqrt(sym.pi) * energy_spread) energy_distribution *= sym.sqrt(2) / 2 elif energy_distribution_function in energy_distribution_functions[ 'Rectangular Level']: energy_offset = conduction_band_energy - trap_central_energy_level energy_distribution = ( sym.sign(energy - energy_offset + energy_spread / 2) + 1) / 2 energy_distribution *= ( sym.sign(energy_offset + energy_spread / 2 - energy) + 1) / 2 energy_distribution /= energy_spread else: raise Exception( 'The distribution function supplied is not supported!') return energy_distribution
def lambd_eq_maker(self, t, x_state, U_input): # for_ode_int My_helicopter = Helicopter() symp_eq = My_helicopter.Helicopter_model(t, x_state, U_input) jacobian = ((sp.Matrix(symp_eq)).jacobian(x_state)).replace( sp.DiracDelta(sp.sqrt(x_state[0] ** 2 + x_state[1] ** 2)), 0 ) J_symb_math = sp.lambdify((x_state, t) + U_input, jacobian, modules=["numpy"]) symb_math = sp.lambdify((x_state, t) + U_input, symp_eq, modules=["numpy"]) return symb_math, J_symb_math
def normalize_dirac_delta_term(term, target): """Given a term of the form "f(n) δ(g(n))", shift n such that g(n) is `target`""" n = sympy.symbols('n', integer=True) coeff, delta = split_dirac_delta(term) delta_arg = delta.args[0] if delta_arg == target: return term else: for shift in [1, -1]: mapping = {n: n + shift} delta_arg_new = delta_arg.subs(mapping).simplify() if delta_arg_new == target: return coeff.subs(mapping) * sympy.DiracDelta(delta_arg_new) raise ValueError("Cannot bring %s to δ(%s)" % (term, target))
def inverse_laplace_damped_sin(expr, s, t, **assumptions): ncoeffs, dcoeffs = expr.coeffs() K = ncoeffs[0] / dcoeffs[0] ncoeffs = [(c / ncoeffs[0]) for c in ncoeffs] dcoeffs = [(c / dcoeffs[0]) for c in dcoeffs] if len(ncoeffs) > 3 or len(dcoeffs) > 3: raise ValueError('Not a second-order response') omega0 = sym.sqrt(dcoeffs[2]) zeta = dcoeffs[1] / (2 * omega0) if zeta.is_constant() and zeta > 1: print('Warning: expression is overdamped') sigma1 = (zeta * omega0).simplify() omega1 = (omega0 * sym.sqrt(1 - zeta**2)).simplify() K = (K / omega1).simplify() E = sym.exp(-sigma1 * t) S = sym.sin(omega1 * t) h = K * E * S # If overdamped #h = K * sym.exp(-sigma1 * t) * sym.sinh(omega0 * mu * t) if len(ncoeffs) == 1: return sym.S.Zero, h C = sym.cos(omega1 * t) kCd = omega1 kSd = -sigma1 hd = K * E * (kCd * C + kSd * S) if len(ncoeffs) == 2: return sym.S.Zero, K * E * (kCd * C + (ncoeffs[1] + kSd) * S) kCdd = -2 * omega1 * sigma1 kSdd = sigma1**2 - omega1**2 G = K * E * ((kCdd + ncoeffs[1] * kCd) * C + (kSdd + ncoeffs[1] * kSd + ncoeffs[2]) * S) return K * kCd * sym.DiracDelta(t), G
def inverse_laplace_power(expr, s, t, **assumptions): # Handle expressions with a power of s. if not (expr.is_Pow and expr.args[0] == s): raise ValueError('Expression %s is not a power of s' % expr) exponent = expr.args[1] # Have many possible forms; the common ones are: # s**a, s**-a, s**(1+a), s**(1-a), s**-(1+a), s**(a-1) # Cannot tell if 1-a is positive. if exponent.is_positive: # Unfortunately, SymPy does not seem to support fractional # derivatives... return sym.Derivative(sym.DiracDelta(t), t, exponent, evaluate=False) if exponent.is_negative: return sym.Pow(t, -exponent - 1) / sym.Gamma(-exponent) raise ValueError('Cannot determine sign of exponent for %s' % expr)
import sympy as sp from sympy.abc import x sp.init_printing() # %% Se definen las cargas distribuidas de acuerdo con la Tabla # Caso 2: carga puntual qpunt = lambda p, a: p * sp.DiracDelta(x - a) # Caso 5: carga distribuida variable qdist = lambda f, a, b: sp.Piecewise((f, (a < x) & (x < b)), (0, True)) # Funcion rectangular: si x>a y x<b retorne 1 sino retorne 0 rect = lambda a, b: sp.Piecewise((1, (a < x) & (x < b)), (0, True)) # Se especifica el vector de cargas q(x) q = qdist(-12, 10, 16) + qpunt(-30, 5) # Se define una función que hace el código más corto y legible integre = lambda f, x: sp.integrate(f, x, meijerg=False) # %% Se define la geometría de la viga y las propiedades del material b = 0.1 # Ancho de la viga, m h = 0.3 # Altura de la viga, m E = 210e6 # Modulo de elasticidad de la viga, kPa I = (b * h * h * h) / 12 # Momento de inercia en z, m^4 # %% Se resuelve la ecuacion diferencial tramo por tramo # Tramo 1 C1_1, C1_2, C1_3, C1_4 = sp.symbols('C1_1 C1_2 C1_3 C1_4') q1 = q * rect(0, 10) # restriccion de q al tramo 1
# symbols t = Symbol('t', positive=True) zeta = Symbol('\zeta', positive=True) omegan = Symbol('\omega_n', positive=True) omegad = Symbol('\omega_d', positive=True) epsilon = Symbol(r'\varepsilon', positive=True) tn = Symbol('t_n', positive=True) P0 = Symbol('P0') m = Symbol('m', positive=True) u0 = 0 v0 = 0 # unknown function u = Function('u')(t) # solving ODE (mass-normalized EOM) f = P0*sympy.DiracDelta(t-tn) ics = {u.subs(t, 0): u0, u.diff(t).subs(t, 0): v0, } sol = dsolve(u.diff(t, t) + 2*zeta*omegan*u.diff(t) + omegan**2*u - f/m, ics=ics) display(sympy.simplify(sol.rhs)) from sympy.plotting import plot plot(sol.rhs.subs({omegan: 10, zeta: 0.1, tn: 3, P0: 1, m: 3}), (t, 0, 10), adaptive=False, nb_of_points=1000, ylabel='$u(t)$')
def eval_cross_section(interactionfile, spinfile, lattice, arg, tau_list, h_list, k_list, l_list, w_vect_list, direction, temperature, kmin, kmax, steps, eief, efixed=14.7): """ Calculates the cross_section given the following parameters: interactionfile, spinfile - files to get atom data lattice - Lattice object from tripleaxisproject arg - reduced list of operator combinations tau_list - list of tau position w_list - list of w's probed direction - direction of scan temp - temperature kmin - minimum value of k to scan kmax - maximum value of k to scan steps - number of steps between kmin, kmax eief - True if the energy scheme is Ei - Ef, False if it is Ef - Ei efixed - value of the fixed energy, either Ei or Ef """ # Read files, get atom_list and such atom_list, jnums, jmats, N_atoms_uc = readFiles(interactionfile, spinfile) N_atoms = len(atom_list) N = N_atoms # TEMPORARY TO OVERRIDE ATOM_LIST ABOVE # atom1 = atom(pos = [0.00,0,0], neighbors = [1], interactions = [0], int_cell = [0], # atomicNum = 26, valence = 3, spinRmatrix=spm.Matrix([[1, 0, 0],[0, 1, 0],[0, 0, 1]])) # atom2 = atom(pos = [0.25,0,0], neighbors = [0,2], interactions = [0], int_cell = [0], # atomicNum = 26, valence = 3, spinRmatrix=spm.Matrix([[1, 0, 0],[0, 1, 0],[0, 0, 1]])) # atom3 = atom(pos = [0.50,0,0], neighbors = [1,3], interactions = [0], int_cell = [0], # atomicNum = 26, valence = 3, spinRmatrix=spm.Matrix([[1, 0, 0],[0, 1, 0],[0, 0, 1]])) # atom4 = atom(pos = [0.75,0,0], neighbors = [2], interactions = [0], int_cell = [0], # atomicNum = 26, valence = 3, spinRmatrix=spm.Matrix([[1, 0, 0],[0, 1, 0],[0, 0, 1]])) # atom_list,N_atoms_uc = ([atom1, atom2, atom3, atom4],1) N_atoms = len(atom_list) # Get Hsave to calculate its eigenvalues (Hsave, charpoly, eigs) = calculate_dispersion(atom_list, N_atoms_uc, N_atoms, jmats, showEigs=True) print "Calculated: Dispersion Relation" # Generate kappa's from (h,k,l) kaprange = [] kapvect = [] if len(h_list) == len(k_list) == len(l_list): for i in range(len(h_list)): kappa = lattice.modvec(h_list[i], k_list[i], l_list[i], 'latticestar') kaprange.append(kappa[0]) kapvect.append(np.array([h_list[i], k_list[i], l_list[i]])) # kapvect.append(np.array([h_list[i]/kappa,k_list[i]/kappa,l_list[i]/kappa])) else: raise Exception('h,k,l not same lengths') # Generate q's from kappa and tau pqrange = [] mqrange = [] for tau in tau_list: ptemp = [] mtemp = [] for kap in kapvect: #tau = lattice.modvec(tau[0],tau[1],tau[2], 'latticestar') ptemp.append(kap - tau) mtemp.append(tau - kap) pqrange.append(ptemp) mqrange.append(mtemp) # Calculate w_q's using q qrange = [] # krange = [] wrange = [] if 1: # Change this later for set in pqrange: temp = [] temp1 = [] for q in set: eigs = calc_eigs(Hsave, q[0] * direction['kx'], q[1] * direction['ky'], q[2] * direction['kz']) # Take only one set of eigs. Should probably have a flag here. temp.append(eigs[0]) # krange.append(np.array([q*direction['kx'], q*direction['ky'], q*direction['kz']])) temp1.append(q) wrange.append(temp) qrange.append(temp1) print "Calculated: Eigenvalues" wrange = np.array(np.real(wrange)) qrange = np.array(np.real(qrange)) kaprange = np.array(np.real(kaprange)) print qrange.shape print wrange.shape print kaprange.shape # Calculate w (not _q) as well as kp/k w_calc = [] kpk = [] if eief == True: for tau in tau_list: temp = [] temp1 = [] for om in w_vect_list: temp.append(om - efixed) temp1.append(np.sqrt(om / efixed)) w_calc.append(temp) kpk.append(temp1) else: for tau in tau_list: temp = [] temp1 = [] for om in w_vect_list: temp.append(-(om - efixed)) temp1.append(np.sqrt(efixed / om)) w_calc.append(temp) kpk.append(temp1) w_calc = np.array(np.real(w_calc)) # Grab Form Factors ff_list = [] s = sp.Symbol('s') for i in range(N_atoms): el = elements[atom_list[i].atomicNum] val = atom_list[i].valence if val != None: Mq = el.magnetic_ff[val].M_Q(kaprange) else: Mq = el.magnetic_ff[0].M_Q(kaprange) ff_list.append(Mq) print "Calculated: Form Factors" # Other Constants gamr0 = 2 * 0.2695 * 10**(-12) #sp.Symbol('gamma', commutative = True) hbar = 1.0 # 1.05457148*10**(-34) #sp.Symbol('hbar', commutative = True) g = 2. #sp.Symbol('g', commutative = True) # Kappa vector kap = sp.Symbol( 'kappa', real=True ) #spm.Matrix([sp.Symbol('kapx',real = True),sp.Symbol('kapy',real = True),sp.Symbol('kapz',real = True)]) t = sp.Symbol('t', real=True) w = sp.Symbol('w', real=True) W = sp.Symbol('W', real=True) tau = sp.Symbol('tau', real=True) q = sp.Symbol('q', real=True) L = sp.Symbol('L', real=True) boltz = 1. #1.3806503*10**(-23) # Wilds for sub_in method A = sp.Wild('A', exclude=[0, t]) B = sp.Wild('B', exclude=[0, t]) C = sp.Wild('C') D = sp.Wild('D') K = sp.Wild('K') # First the exponentials are turned into delta functions: for i in range(len(arg)): for j in range(N): print '1', arg[i][j] arg[i][j] = sp.powsimp( arg[i] [j]) #sp.powsimp(arg[i][j], deep = True, combine = 'all') arg[i][j] = ( arg[i][j] * exp(-I * w * t) * exp(I * kap * L)).expand( ) # * exp(I*inner_prod(spm.Matrix(atom_list[j].pos).T,kap)) arg[i][j] = sp.powsimp( arg[i] [j]) #sp.powsimp(arg[i][j], deep = True, combine = 'all') # print '2', arg[i][j] arg[i][j] = sub_in( arg[i][j], exp(I * t * A + I * t * B + I * C + I * D + I * K), sp.DiracDelta(A * t + B * t + C + D + K)) #*sp.DiracDelta(C)) # print '3', arg[i][j] arg[i][j] = sub_in( arg[i][j], sp.DiracDelta(A * t + B * t + C * L + D * L + K * L), sp.DiracDelta(A * hbar + B * hbar) * sp.simplify(sp.DiracDelta(C + D + K + tau))) # print '4', arg[i][j] arg[i][j] = sub_in(arg[i][j], sp.DiracDelta(-A - B) * sp.DiracDelta(C), sp.DiracDelta(A + B) * sp.DiracDelta(C)) print '5', arg[i][j] print "Applied: Delta Function Conversion" # Grabs the unit vectors from the back of the lists. unit_vect = [] kapxhat = sp.Symbol('kapxhat', commutative=False) kapyhat = sp.Symbol('kapyhat', commutative=False) kapzhat = sp.Symbol('kapzhat', commutative=False) for i in range(len(arg)): unit_vect.append(arg[i].pop()) # Subs the actual values for kx,ky,kz, omega_q and n_q into the operator combos # The result is basically a nested list: # # csdata = [ op combos ] # op combos = [ one combo per atom ] # 1 per atom = [ evaluated exp ] # csdata = [] for i in range(len(arg)): temp1 = [] for j in range(len(arg[i])): temp2 = [] for k in range(len(tau_list)): temp3 = [] print i, j, k for g in range(len(qrange[k])): pvalue = tau_list[k] + kapvect[g] + qrange[k][g] mvalue = tau_list[k] + kapvect[g] - qrange[k][g] if pvalue[0] == 0 and pvalue[1] == 0 and pvalue[2] == 0: arg[i][j] = arg[i][j].subs( sp.DiracDelta(kap + tau + q), sp.DiracDelta(0)) else: arg[i][j] = arg[i][j].subs( sp.DiracDelta(kap + tau + q), 0) if mvalue[0] == 0 and mvalue[1] == 0 and mvalue[2] == 0: arg[i][j] = arg[i][j].subs( sp.DiracDelta(kap + tau - q), sp.DiracDelta(0)) else: arg[i][j] = arg[i][j].subs( sp.DiracDelta(kap + tau - q), 0) wq = sp.Symbol('wq', real=True) nq = sp.Symbol('n%i' % (k, ), commutative=False) arg[i][j] = arg[i][j].subs(wq, wrange[k][g]) arg[i][j] = arg[i][j].subs(w, w_calc[k][g]) n = sp.Pow( sp.exp(hbar * wrange[k][g] / boltz * temperature) - 1, -1) arg[i][j] = arg[i][j].subs(nq, n) temp3.append(arg[i][j]) temp2.append(temp3) temp1.append(temp2) csdata.append(temp1) ## print arg[i][j] # for g in range(len(kaprange)): # arg[i][j] = arg[i][j].subs(kap, kaprange[g]) # for g in range(len(krange)): ## print 'calculating' # temp3 = [] # wg = sp.Symbol('w%i'%(g,), real = True) # ng = sp.Symbol('n%i'%(g,), commutative = False) ## kx = sp.Symbol('kx', real = True, commutative = True) ## ky = sp.Symbol('ky', real = True, commutative = True) ## kz = sp.Symbol('kz', real = True, commutative = True) ## arg[i][j] = arg[i][j].subs(kx,krange[g][0]) ## arg[i][j] = arg[i][j].subs(ky,krange[g][1]) ## arg[i][j] = arg[i][j].subs(kz,krange[g][2]) # arg[i][j] = arg[i][j].subs(wg,wrange[g]) # arg[i][j] = arg[i][j].subs(w,w_calc[g]) # nq = sp.Pow( sp.exp(hbar*wrange[g]/boltz*temp) - 1 ,-1) # arg[i][j] = arg[i][j].subs(ng,nq) ## arg[i][j] = arg[i][j].subs(tau,tau_list[0]) # # temp3.append(arg[i][j]) ## print arg[i][j] # temp2.append(temp3) ## print arg[i][j] # csdata.append(temp2) print csdata # Front constants and stuff for the cross-section front_constant = 1.0 # (gamr0)**2/(2*pi*hbar) front_func = (1. / 2.) * g #*F(k) vanderwaals = 1. #exp(-2*W) csrange = [] if 1: temp1 = [] temp2 = [] for q in range(len(qrange)): print 'calculating' for ii in range(len(csdata)): for jj in range(len(csdata[ii])): temp1.append(csdata[ii][jj]) # Put on gamr0, 2pi hbar, form factor, kp/k, vanderwaals first dif = front_func**2 * front_constant # * kpk[q][0] * vanderwaals * ff_list[0][q] # for vect in unit_vect: # vect.subs(kapxhat,kapvect[q][0][0]) # vect.subs(kapyhat,kapvect[q][1][0]) # vect.subs(kapzhat,kapvect[q][2][0]) print 'diff', dif print 'temp1', temp1 print sum(temp1) dif = (dif * sum(temp1)) # * sum(unit_vect))#.expand() csrange.append(dif) print "Calculated: Cross-section" csrange = np.real(csrange) csrange = np.array(csrange) xi = qrange yi = wrange zi = csrange Z = np.zeros((xi.shape[0], yi.shape[0])) Z[range(len(xi)), range(len(yi))] = zi pylab.contourf(xi, yi, Z) pylab.colorbar() pylab.show()
def blahblah(x, y, z): if y > z: check = lambda x, y: x + y else: check = lambda x, y: x**y return check(x, y) print blahblah(1, 2, 3) print blahblah(3, 2, 1) x = sp.Symbol('x') f = lambda x: sp.sin(x + 2) print f(x) if 0: d, e = sp.symbols('de') print(sp.DiracDelta(0) * d + e).evalf() a = 1.00001 b = 1.00001 print sp.DiracDelta(a - b) c = 1.00000 print sp.DiracDelta(a - c) * d if 0: x = sp.Symbol('x', commutative=False) y = sp.Symbol('y', commutative=False) print(x * y * x * y).subs(x * y, 2) a, b = sp.symbols('ab') print(x * y).subs(x * y, y * x + 1) print(y * x).subs(x * y, y * x + 1) e = a * b
def fourier_term(expr, t, f, inverse=False): if expr.has(sym.function.AppliedUndef) and expr.args[0] == t: # TODO, handle things like 3 * v(t), a * v(t), 3 * t * v(t), v(t-T), # v(4 * a * t), etc. if not isinstance(expr, sym.function.AppliedUndef): raise ValueError('Could not compute Fourier transform for ' + str(expr)) # Convert v(t) to V(f), etc. name = expr.func.__name__ if inverse: name = name[0].lower() + name[1:] + '(%s)' % -f else: name = name[0].upper() + name[1:] + '(%s)' % f return sym.sympify(name) # Check for constant. if not expr.has(t): return expr * sym.DiracDelta(f) one = sym.sympify(1) const = one other = one exps = one factors = expr.as_ordered_factors() for factor in factors: if not factor.has(t): const *= factor else: if factor.is_Function and factor.func == sym.exp: exps *= factor else: other *= factor if other != 1 and exps == 1: if other == t: return const * sym.I * 2 * sym.pi * sym.DiracDelta(f, 1) if other == t**2: return const * (sym.I * 2 * sym.pi)**2 * sym.DiracDelta(f, 2) # Sympy incorrectly gives exp(-a * t) instead of exp(-a * t) * # Heaviside(t) if other.is_Pow and other.args[1] == -1: foo = other.args[0] if foo.is_Add and foo.args[1].has(t): bar = foo.args[1] / t if not bar.has(t) and bar.has(sym.I): a = -(foo.args[0] * 2 * sym.pi * sym.I) / bar return const * sym.exp(-a * f) * sym.Heaviside( f * sym.sign(a)) # Punt and use SymPy. Should check for t**n, t**n * exp(-a * t), etc. return fourier_sympy(expr, t, f) args = exps.args[0] foo = args / t if foo.has(t): # Have exp(a * t**n), SymPy might be able to handle this return fourier_sympy(expr, t, f) if exps != 1 and foo.has(sym.I): return const * sym.DiracDelta(f - foo / (sym.I * 2 * sym.pi)) return fourier_sympy(expr, t, f)
def generate_cross_section(atom_list, arg, q, real_list, recip_list): """Generates the Cross-Section Formula for the one magnon case""" N = len(atom_list) gam = 1.913 #sp.Symbol('gamma', commutative = True) r = sp.Symbol('r0', commutative=True) h = 1. # 1.05457148*10**(-34) #sp.Symbol('hbar', commutative = True) k = sp.Symbol('k', commutative=True) kp = sp.Symbol('kp', commutative=True) g = sp.Symbol('g', commutative=True) F = sp.Function('F') def FF(arg): F = sp.Function('F') if arg.shape == (3, 1) or arg.shape == (1, 3): return sp.Symbol("%r" % (F(arg.tolist()), ), commutative=False) kap = spm.Matrix([ sp.Symbol('kapx', commutative=False), sp.Symbol('kapy', commutative=False), sp.Symbol('kapz', commutative=False) ]) t = sp.Symbol('t', commutative=True) w = sp.Symbol('w', commutative=True) W = sp.Symbol('W', commutative=False) kappa = sp.Symbol('kappa', commutative=False) tau = sp.Symbol('tau', commutative=False) # Wilds for sub_in method A = sp.Wild('A', exclude=[0]) B = sp.Wild('B', exclude=[0]) C = sp.Wild('C') D = sp.Wild('D') front_constant = (gam * r)**2 / (2 * pi * h) * (kp / k) * N front_func = (1. / 2.) * g #*F(k) vanderwaals = exp(-2 * W) temp2 = [] temp3 = [] temp4 = [] # Grabs the unit vectors from the back of the lists. unit_vect = [] kapx = sp.Symbol('kapxhat', ) kapy = sp.Symbol('kapyhat', commutative=False) kapz = sp.Symbol('kapzhat', commutative=False) for i in range(len(arg)): unit_vect.append(arg[i].pop()) # for ele in unit_vect: # ele = ele.subs(kapx,spm.Matrix([1,0,0])) # ele = ele.subs(kapy,spm.Matrix([0,1,0])) # ele = ele.subs(kapz,spm.Matrix([0,0,1])) # This is were the heart of the calculation comes in. # First the exponentials are turned into delta functions: for i in range(len(arg)): for j in range(N): arg[i][j] = sp.powsimp(arg[i][j], deep=True, combine='all') arg[i][j] = arg[i][j] * exp(-I * w * t) * exp( I * inner_prod(spm.Matrix(atom_list[j].pos).T, kap)) arg[i][j] = sp.powsimp(arg[i][j], deep=True, combine='all') arg[i][j] = sub_in(arg[i][j], exp(I * t * A + I * t * B + C), sp.DiracDelta(A * t + B * t + C / I)) #*sp.DiracDelta(C)) arg[i][j] = sub_in( arg[i][j], sp.DiracDelta(A * t + B * t + C), sp.DiracDelta(A * h + B * h) * sp.DiracDelta(C + tau)) arg[i][j] = sub_in(arg[i][j], sp.DiracDelta(-A - B), sp.DiracDelta(A + B)) print arg[i][j] print "Applied: Delta Function Conversion" # for ele in arg: # for subele in ele: # temp2.append(subele) # temp3.append(sum(temp2)) # # for i in range(len(temp3)): # temp4.append(unit_vect[i] * temp3[i]) for k in range(len(arg)): temp4.append(arg[k][q]) dif = (front_func**2 * front_constant * vanderwaals * sum(temp4) ) #.expand()#sp.simplify(sum(temp4))).expand() print "Complete: Cross-section Calculation" return dif
import sympy as sp from sympy.abc import x sp.init_printing() # %% Se definen las cargas distribuidas de acuerdo con la Tabla # Caso 2: carga puntual qpunt = lambda p,a : p*sp.DiracDelta(x-a) # Caso 5: carga distribuida variable qdist = lambda f,a,b : sp.Piecewise((f, (a < x) & (x < b)), (0, True)) # Funcion rectangular: si x>a y x<b retorne 1 sino retorne 0 rect = lambda a,b : sp.Piecewise((1, (a < x) & (x < b)), (0, True)) # Se define una función que hace el código más corto y legible integre = lambda f, x : sp.integrate(f, x, meijerg=False) # %% Se define la geometría de la viga y las propiedades del material b = 0.1 # Ancho de la viga, m h = 0.3 # Altura de la viga, m E = 210e6 # Módulo de elasticidad de la viga, kPa I = (b*h*h*h)/12 # Momento de inercia en z, m^4 # %% FORMA 1: # Momento flector mflec = lambda m,a : -m*sp.DiracDelta(x-a, 1) # Se especifica el vector de cargas q(x) q = qpunt(-5,1) + qdist(-3*x/2,2,4) + mflec(-8,3.5) + mflec(3,5)
import sympy as sp from IPython.display import display sp.init_printing() # pretty printing # Define impulse and unit step as functions of t t = sp.symbols('t') imp = sp.DiracDelta(t) ustep = sp.Heaviside(t) #ustep = sp.Piecewise( (0, t<1), (1, True)); # diff() doesn't give delta function?! # Setup differential equation x = sp.Function('x') y = sp.Function('y') RC = sp.symbols('RC') #, real=True); lp1de = sp.Eq(y(t) + RC * sp.diff(y(t), t), x(t)) #print(lp1de); display(lp1de); # Generic solution y_sl0e = sp.dsolve(lp1de, y(t)) y_sl0r = y_sl0e.rhs # take only right hand side #print(y_sl0e); display(y_sl0e); # Initial condition a0 = sp.symbols('a0') cnd1 = sp.Eq(y_sl0r.subs(t, -1), a0) # y(-1) = a0 #cnd2 = sp.Eq(y_sl0r.diff(t).subs(t, -1), b0) # y'(-1) = b0 #print(cnd1); display(cnd1); # Solve for C1: magic brackets in solve() returns result as dictionary
def eval_cross_section(N_atoms_uc, csection, kaprange, qlist, tau_list, eig_list, kapvect, wtlist): print "begin part 2" gamr0 = 2 * 0.2695e-12 #sp.Symbol('gamma', commutative = True) hbar = sp.S( 1.0) # 1.05457148*10**(-34) #sp.Symbol('hbar', commutative = True) g = 2. #sp.Symbol('g', commutative = True) # Kappa vector kap = sp.Symbol( 'kappa', real=True ) #spm.Matrix([sp.Symbol('kapx',real = True),sp.Symbol('kapy',real = True),sp.Symbol('kapz',real = True)]) t = sp.Symbol('t', real=True) w = sp.Symbol('w', real=True) W = sp.Symbol('W', real=True) tau = sp.Symbol('tau', real=True) Q = sp.Symbol('q', real=True) L = sp.Symbol('L', real=True) lifetime = sp.Symbol('V', real=True) boltz = 8.617343e-2 kapxhat = sp.Symbol('kapxhat', real=True) kapyhat = sp.Symbol('kapyhat', real=True) kapzhat = sp.Symbol('kapzhat', real=True) kapunit = kapvect.copy() kapunit[:, 0] = kapvect[:, 0] / kaprange kapunit[:, 1] = kapvect[:, 1] / kaprange kapunit[:, 2] = kapvect[:, 2] / kaprange nkpts = len(kaprange) nqpts = 2 * nkpts csdata = [] wq = sp.Symbol('wq', real=True) for k in range(len(tau_list)): temp1 = [] for g in range(nqpts): temp2 = [] for i in range(len(eig_list[k][g])): #temp = eval_it(k,g,i,nkpts,csection) temp = csection for num in range(N_atoms_uc): nq = sp.Symbol('n%i' % (num, ), real=True) #n = sp.Pow( sp.exp(-np.abs(eig_list[k][g][i])/boltz/temperature) - 1 ,-1) n = sp.S(0.0) temp = temp.subs(nq, n) #if g==0: if g < nkpts: value = kapvect[g] - tau_list[k] - qlist[k][g] if eq(value[0], 0) == 0 and eq(value[1], 0) == 0 and eq( value[2], 0) == 0: temp = temp.subs(sp.DiracDelta(kap - tau - Q), sp.S(1)) temp = temp.subs(sp.DiracDelta(-kap + tau + Q), sp.S( 1)) # recall that the delta function is symmetric else: temp = temp.subs(sp.DiracDelta(kap - tau - Q), sp.S(0)) temp = temp.subs(sp.DiracDelta(-kap + tau + Q), sp.S(0)) temp = temp.subs(kapxhat, kapunit[g, 0]) temp = temp.subs(kapyhat, kapunit[g, 1]) temp = temp.subs(kapzhat, kapunit[g, 2]) #value =kapvect[g//2]- tau_list[k] + qlist[k][g] #if g%2!=0: elif g >= nkpts: value = kapvect[g - nkpts] - tau_list[k] - qlist[k][g] if eq(value[0], 0) == 0 and eq(value[1], 0) == 0 and eq( value[2], 0) == 0: temp = temp.subs(sp.DiracDelta(kap - tau + Q), sp.S(1)) temp = temp.subs(sp.DiracDelta(-kap + tau - Q), sp.S(1)) else: temp = temp.subs(sp.DiracDelta(kap - tau + Q), sp.S(0)) temp = temp.subs(sp.DiracDelta(-kap + tau - Q), sp.S(0)) temp = temp.subs(kapxhat, kapunit[g - nkpts, 0]) temp = temp.subs(kapyhat, kapunit[g - nkpts, 1]) temp = temp.subs(kapzhat, kapunit[g - nkpts, 2]) value = tau_list[k] if eq(value[0], 0) == 0 and eq(value[1], 0) == 0 and eq( value[2], 0) == 0: temp = temp.subs(sp.DiracDelta(kap - tau - Q), sp.S(1)) temp = temp.subs(sp.DiracDelta(-kap + tau + Q), sp.S(1)) # temp = temp.subs(sp.DiracDelta(kap - tau + Q), sp.S(1)) temp = temp.subs(sp.DiracDelta(-kap + tau - Q), sp.S(1)) #temp = temp.subs(kapxhat,kapunit[g//2,0]) #temp = temp.subs(kapyhat,kapunit[g//2,1]) #temp = temp.subs(kapzhat,kapunit[g//2,2]) value = eig_list[k][g][i] - wtlist[g] #print '1',temp temp = temp.subs(wq, eig_list[k][g][i]) temp = temp.subs(w, wtlist[g]) if 0: if eq(value, 0) == 0: temp = temp.subs(sp.DiracDelta(wq - w), sp.S(1)) else: temp = temp.subs(sp.DiracDelta(wq - w), sp.S(0)) if 0: if eq(eig_list[k][g][i], wtlist[g]) == 0: G = sp.Wild('G', exclude=[Q, kap, tau, w]) temp = sub_in(temp, sp.DiracDelta(G - A * w), sp.S(1)) elif eq(eig_list[k][g][i], -wtlist[g]) == 0: G = sp.Wild('G', exclude=[Q, kap, tau, w]) temp = sub_in(temp, sp.DiracDelta(G - A * w), sp.S(1)) else: temp = temp.subs(w, wtlist[g]) # print '4',temp temp2.append(temp) temp1.append(temp2) csdata.append(temp1) #print csdata # Front constants and stuff for the cross-section front_constant = 1.0 #(gamr0)**2#/(2*pi*hbar) front_func = (1. / 2.) * g #*F(k) debye_waller = 1. #exp(-2*W) cstemp = [] for g in range(nqpts): for k in range(len(tau_list)): cstemp.append(csdata[k][g][0].subs(lifetime, sp.S(.1))) print cstemp sys.exit() qtlist = np.array(qlist, 'Float64').reshape((nqpts * len(tau_list), 3))[:, 0] xi = qtlist yi = wtlist zi = np.array(cstemp, 'Float64') Z = matplotlib.mlab.griddata(xi, yi, zi, xi, yi) zmin, zmax = np.min(Z), np.max(Z) locator = ticker.MaxNLocator(10) # if you want no more than 10 contours locator.create_dummy_axis() locator.set_bounds(zmin, zmax) levs = locator() levs[0] = 1.0 print zmin, zmax #zm=ma.masked_where(Z<=0,Z) zm = Z print zm print levs plt.contourf( xi, yi, Z, levs) #, norm=matplotlib.colors.LogNorm(levs[0],levs[len(levs)-1])) l_f = ticker.LogFormatter(10, labelOnlyBase=False) cbar = plt.colorbar(ticks=levs, format=l_f) plt.show()
def inverse_laplace_ratfun(expr, s, t, **assumptions): sexpr = Ratfun(expr, s) damping = assumptions.get('damping', None) if assumptions.get('damped_sin', False): if sexpr.degree == 2: return inverse_laplace_damped_sin(sexpr, s, t, **assumptions) #if False and sexpr.degree == 3 and Ratfun(expr * s).degree == 2: # return inverse_laplace_damped_sin3(sexpr, s, t, **assumptions) Q, M, D, delay, undef = sexpr.as_QMD() cresult = sym.S.Zero if Q: Qpoly = sym.Poly(Q, s) C = Qpoly.all_coeffs() for n, c in enumerate(C): cresult += c * sym.diff(sym.DiracDelta(t), t, len(C) - n - 1) expr = M / D for factor in expr.as_ordered_factors(): if factor == sym.oo: return factor sexpr = Ratfun(expr, s) poles = sexpr.poles(damping=damping) polesdict = {} for pole in poles: polesdict[pole.expr] = pole.n uresult = sym.S.Zero for pole in poles: p = pole.expr # Number of occurrences of the pole. o = polesdict[p] if o == 0: continue if o == 1: pc = pole.conjugate r = sexpr.residue(p, poles) if pc != p and pc in polesdict: # Remove conjugate from poles and process pole with its # conjugate. Unfortunately, for symbolic expressions # we cannot tell if a quadratic has two real poles, # a repeated real pole, or a complex conjugate pair of poles. polesdict[pc] -= 1 p_re = sym.re(p) p_im = sym.im(p) r_re = sym.re(r) r_im = sym.im(r) et = sym.exp(p_re * t) uresult += 2 * r_re * et * sym.cos(p_im * t) uresult -= 2 * r_im * et * sym.sin(p_im * t) else: uresult += r * sym.exp(p * t) continue # Handle repeated poles. expr2 = expr * (s - p)**o expr2 = expr2.simplify() for n in range(1, o + 1): m = o - n r = sym.limit(sym.diff(expr2, s, m), s, p) / sym.factorial(m) uresult += r * sym.exp(p * t) * t**(n - 1) # cresult is a sum of Dirac deltas and its derivatives so is known # to be causal. return cresult, uresult
def generate_cross_section(interactionfile, spinfile, lattice, arg, tau_list, h_list, k_list, l_list, w_list, temperature, steps, eief, efixed=14.7): """ Calculates the cross_section given the following parameters: interactionfile, spinfile - files to get atom data lattice - Lattice object from tripleaxisproject arg - reduced list of operator combinations tau_list - list of tau position w_list - list of w's probed temp - temperature kmin - minimum value of k to scan kmax - maximum value of k to scan steps - number of steps between kmin, kmax eief - True if fixed Ef efixed - value of the fixed energy, either Ei or Ef """ # Read files, get atom_list and such atom_list, jnums, jmats, N_atoms_uc = readFiles(interactionfile, spinfile) # Get Hsave to calculate its eigenvalues N_atoms = len(atom_list) Hsave = calculate_dispersion(atom_list, N_atoms_uc, N_atoms, jmats, showEigs=False) atom_list = atom_list[:N_atoms_uc] N_atoms = len(atom_list) N = N_atoms print "Calculated: Dispersion Relation" # Generate kappa's from (h,k,l) kaprange = [] kapvect = [] #if len(h_list) == len(k_list) == len(l_list): #for i in range(len(h_list)): #kappa = lattice.modvec(h_list[i],k_list[i],l_list[i], 'latticestar') #kaprange.append(kappa[0]) #kapvect.append(np.array([h_list[i],k_list[i],l_list[i]])) ## kapvect.append(np.array([h_list[i]/kappa,k_list[i]/kappa,l_list[i]/kappa])) #else: #raise Exception('h,k,l not same lengths') # Generate q's from kappa and tau kaprange = lattice.modvec(h_list, k_list, l_list, 'latticestar') nkpts = len(kaprange) kapvect = np.empty((nkpts, 3), 'Float64') kapvect[:, 0] = h_list kapvect[:, 1] = k_list kapvect[:, 2] = l_list # print kapvect.shape # print kaprange.shape kapunit = kapvect.copy() kapunit[:, 0] = kapvect[:, 0] / kaprange kapunit[:, 1] = kapvect[:, 1] / kaprange kapunit[:, 2] = kapvect[:, 2] / kaprange #plusq=kappa-tau plusq = [] minusq = [] qlist = [] ones_list = np.ones((1, nkpts), 'Float64') #wtlist=np.ones((1,nkpts*2),'Float64').flatten() wtlist = np.hstack([w_list, w_list]) #weven=np.array(range(0,nkpts*2,2)) #wodd=np.array(range(1,nkpts*2,2)) #wtlist[wodd]=w_list #wtlist[weven]=w_list qtlist = [] for tau in tau_list: taui = np.ones((nkpts, 3), 'Float64') taui[:, 0] = ones_list * tau[0] taui[:, 1] = ones_list * tau[1] taui[:, 2] = ones_list * tau[2] kappa_minus_tau = kapvect - taui tau_minus_kappa = taui - kapvect qlist.append(np.vstack([kappa_minus_tau, tau_minus_kappa])) #calculate kfki nqpts = nkpts * 2 kfki = calc_kfki(w_list, eief, efixed) eig_list = [] # print qlist for q in qlist: #eigs = calc_eigs_direct(Hsave,q[:,0],q[:,1],q[:,2]) eigs = Hsave.eigenvals().keys() eig_list.append(eigs) print "Calculated: Eigenvalues" # print len(qlist) # print len(eig_list[0]) # sys.exit() # Grab Form Factors #----Commented out 9/14/09 by Tom becuase of magnetic_ff error-------------- #ff_list = [] #s = sp.Symbol('s') #for i in range(N_atoms): #el = elements[atom_list[i].atomicNum] #val = atom_list[i].valence #if val != None: #Mq = el.magnetic_ff[val].M_Q(kaprange) #else: #Mq = el.magnetic_ff[0].M_Q(kaprange) #ff_list.append(Mq) #print "Calculated: Form Factors" #-------------------------------------------------------------------------- # Other Constants gamr0 = 2 * 0.2695e-12 #sp.Symbol('gamma', commutative = True) hbar = sp.S( 1.0) # 1.05457148*10**(-34) #sp.Symbol('hbar', commutative = True) g = 2. #sp.Symbol('g', commutative = True) # Kappa vector kap = sp.Symbol( 'kappa', real=True ) #spm.Matrix([sp.Symbol('kapx',real = True),sp.Symbol('kapy',real = True),sp.Symbol('kapz',real = True)]) t = sp.Symbol('t', real=True) w = sp.Symbol('w', real=True) W = sp.Symbol('W', real=True) tau = sp.Symbol('tau', real=True) Q = sp.Symbol('q', real=True) L = sp.Symbol('L', real=True) lifetime = sp.Symbol('V', real=True) boltz = 8.617343e-2 # Wilds for sub_in method A = sp.Wild('A', exclude=[0, t]) B = sp.Wild('B', exclude=[0, t]) C = sp.Wild('C') D = sp.Wild('D') K = sp.Wild('K') # Grabs the unit vectors from the back of the lists. unit_vect = [] kapxhat = sp.Symbol('kapxhat', real=True) kapyhat = sp.Symbol('kapyhat', real=True) kapzhat = sp.Symbol('kapzhat', real=True) for i in range(len(arg)): unit_vect.append(arg[i].pop()) #print unit_vect unit_vect = sum(unit_vect) print unit_vect csection = 0 for i in range(len(arg)): for j in range(len(arg[i])): csection = csection + arg[i][j] * unit_vect print csection csection = sp.powsimp(csection) csection = (csection * exp(-I * w * t) * exp(I * kap * L)).expand(deep=False) print 'intermediate' #print csection csection = sp.powsimp(csection) csection = sub_in(csection, exp(I * t * A + I * t * B + I * C + I * D + I * K), sp.DiracDelta(A * t + B * t + C + D + K)) csection = sub_in( csection, sp.DiracDelta(A * t + B * t + C * L + D * L), sp.DiracDelta(A * hbar + B * hbar) * sp.simplify(sp.DiracDelta(C + D - tau))) #This is correct #csection = sub_in(csection,sp.DiracDelta(A*t + B*t + C*L + D*L ),sp.simplify(lifetime*sp.DiracDelta(C + D - tau)* #sp.Pow((A-B)**2+lifetime**2,-1))) print "Applied: Delta Function Conversion" # print csection print 'done' ## First the exponentials are turned into delta functions: #for i in range(len(arg)): #for j in range(N): ## print '1', arg[i][j] #arg[i][j] = sp.powsimp(arg[i][j])#sp.powsimp(arg[i][j], deep = True, combine = 'all') #arg[i][j] = (arg[i][j] * exp(-I*w*t) * exp(I*kap*L)).expand()# * exp(I*inner_prod(spm.Matrix(atom_list[j].pos).T,kap)) #arg[i][j] = sp.powsimp(arg[i][j])#sp.powsimp(arg[i][j], deep = True, combine = 'all') ## print '2', arg[i][j] #arg[i][j] = sub_in(arg[i][j],exp(I*t*A + I*t*B + I*C + I*D + I*K),sp.DiracDelta(A*t + B*t + C + D + K))#*sp.DiracDelta(C)) ## print '3', arg[i][j] #arg[i][j] = sub_in(arg[i][j],sp.DiracDelta(A*t + B*t + C*L + D*L + K*L),sp.DiracDelta(A*hbar + B*hbar)*sp.simplify(sp.DiracDelta(C + D + K + tau))) ## print '4', arg[i][j] #arg[i][j] = sub_in(arg[i][j],sp.DiracDelta(-A - B)*sp.DiracDelta(C),sp.DiracDelta(A + B)*sp.DiracDelta(C)) ## arg[i][j] = arg[i][j].subs(-w - wq, w + wq) ## print '5', arg[i][j] print "Applied: Delta Function Conversion" # Subs the actual values for kx,ky,kz, omega_q and n_q into the operator combos # The result is basically a nested list: # # csdata = [ op combos ] # op combos = [ one combo per atom ] # 1 per atom = [ evaluated exp ] # csection = sub_in(csection, sp.DiracDelta(-A - B) * sp.DiracDelta(C), sp.DiracDelta(A + B) * sp.DiracDelta(C)) print "end part 1" #print csection return (N_atoms_uc, csection, kaprange, qlist, tau_list, eig_list, kapvect, wtlist)
def find_dirac_delta_terms(expr): """Return all sub-expressions of the form "x * δ(y)" in `expr`""" _w = sympy.Wild('w') _w2 = sympy.Wild('w2') return list(term for term in expr.find(_w * sympy.DiracDelta(_w2)) if isinstance(term, sympy.Mul))
def product(self, expr, s, t, **kwargs): # Handle expressions with a function of s, e.g., V(s) * Y(s), V(s) # / s etc. if kwargs.get('causal', False): # Assume that all functions are causal in the expression. t1 = Zero t2 = t else: t1 = -sym.oo t2 = sym.oo const, expr = factor_const(expr, s) factors = expr.as_ordered_factors() if len(factors) < 2: cresult, uresult = self.term1(expr, s, t, **kwargs) return const * (cresult + uresult) if (len(factors) > 2 and not # Help s * 1 / (s + R * C) * I(s) isinstance(factors[1], AppliedUndef) and isinstance(factors[2], AppliedUndef)): factors = [factors[0], factors[2], factors[1]] + factors[3:] if isinstance(factors[1], AppliedUndef): # Try to expose more simple cases, e.g. (R + s * L) * V(s) terms = factors[0].expand().as_ordered_terms() if len(terms) >= 2: result = Zero for term in terms: result += self.product(factors[1] * term, s, t, **kwargs) return result * const cresult, uresult = self.term1(factors[0], s, t, **kwargs) result = cresult + uresult intnum = 0 for m in range(len(factors) - 1): if m == 0 and isinstance(factors[1], AppliedUndef): # Note, as_ordered_factors puts powers of s before the functions. if factors[0] == s: # Handle differentiation # Convert s * V(s) to d v(t) / dt result = self.func(factors[1], s, t) result = sym.Derivative(result, t) if not kwargs.get('zero_initial_conditions', True): fname = factors[1].func.__name__ func = sym.Function(fname[0].lower() + fname[1:]) result += func(0) * sym.DiracDelta(t) continue elif factors[0].is_Pow and factors[0].args[ 0] == s and factors[0].args[1] > 0: # Handle higher order differentiation # Convert s ** 2 * V(s) to d^2 v(t) / dt^2 result = self.func(factors[1], s, t) result = sym.Derivative(result, t, factors[0].args[1]) if not kwargs.get('zero_initial_conditions', True): fname = factors[1].func.__name__ func = sym.Function(fname[0].lower() + fname[1:]) v = func(t) order = factors[0].args[1] for m in range(order - 1): result += sym.Derivative(v, t, m).subs(t, 0) * \ sym.DiracDelta(t, order - m - 1) result += sym.Derivative(v, t, order - 1).subs(t, 0) * \ sym.DiracDelta(t) continue elif factors[0].is_Pow and factors[0].args[0] == s and factors[ 0].args[1] == -1: # Handle integration 1 / s * V(s) tau = self.dummy_var(expr, 'tau', level=intnum, real=True) intnum += 1 result = self.func(factors[1], s, tau) result = sym.Integral(result, (tau, t1, t)) continue # Convert product to convolution tau = self.dummy_var(expr, 'tau', level=intnum, real=True) intnum += 1 cresult, uresult = self.term1(factors[m + 1], s, t, **kwargs) expr2 = cresult + uresult result = sym.Integral( result.subs(t, t - tau) * expr2.subs(t, tau), (tau, t1, t2)) return result * const
def ratfun(self, expr, s, t, **kwargs): if kwargs.pop('pdb', False): import pdb pdb.set_trace() sexpr = Ratfun(expr, s) if kwargs.get('damped_sin', False): if sexpr.degree == 2: return self.do_damped_sin(sexpr, s, t) # if False and sexpr.degree == 3 and Ratfun(expr * s).degree == 2: # return self.do_damped_sin3(sexpr, s, t) self.debug('Finding QRPO representation') damping = kwargs.get('damping', None) Q, R, P, O, delay, undef = sexpr.as_QRPO(damping) if delay != 0: # This will be caught and trigger expansion of the expression. self.error('Unhandled delay %s' % delay) cresult = Zero if Q: Qpoly = sym.Poly(Q, s) C = Qpoly.all_coeffs() for n, c in enumerate(C): cresult += c * sym.diff(sym.DiracDelta(t), t, len(C) - n - 1) if R == []: return cresult, 0 uresult = 0 for m, (p, n, A) in enumerate(zip(P, O, R)): # This is zero for the conjugate pole. if R[m] == 0: continue # Search and remove conjugate pair. has_conjpair = False if p.is_complex and kwargs.get('pairs', True): pc = p.conjugate() Ac = A.conjugate() for m2, p2 in enumerate(P[m + 1:]): m2 += m + 1 if n == O[m2] and p2 == pc and R[m2] == Ac: R[m2] = 0 has_conjpair = True break if has_conjpair: # Combine conjugate pairs. p = p.expand(complex=True) A = A.expand(complex=True) p_re = sym.re(p) p_im = sym.im(p) A_re = sym.re(A) A_im = sym.im(A) et = sym.exp(p_re * t) result = 2 * A_re * et * sym.cos(p_im * t) result -= 2 * A_im * et * sym.sin(p_im * t) else: result = A * sym.exp(p * t) if n > 1: result *= t**(n - 1) / sym.factorial(n - 1) uresult += result # cresult is a sum of Dirac deltas and its derivatives so is known # to be causal. return cresult, uresult
def fourier_term(expr, t, f, inverse=False): const, expr = factor_const(expr, t) if isinstance(expr, sym.function.AppliedUndef): return fourier_func(expr, t, f, inverse) * const # TODO add u(t) <--> delta(f) / 2 - j / (2 * pi * f) if expr.has(sym.function.AppliedUndef): # Handle v(t), v(t) * y(t), 3 * v(t) / t etc. return fourier_function(expr, t, f, inverse) * const # Check for constant. if not expr.has(t): return expr * sym.DiracDelta(f) * const one = sym.S.One const1 = const other = one exps = one factors = expr.as_ordered_factors() for factor in factors: if not factor.has(t): const1 *= factor else: if factor.is_Function and factor.func == sym.exp: exps *= factor else: other *= factor sf = -f if inverse else f if other != 1 and exps == 1: if other == t: return const1 * sym.I * 2 * sym.pi * sym.DiracDelta(f, 1) if other == t**2: return const1 * (sym.I * 2 * sym.pi)**2 * sym.DiracDelta(f, 2) # Sympy incorrectly gives exp(-a * t) instead of exp(-a * t) * # Heaviside(t) if other.is_Pow and other.args[1] == -1: foo = other.args[0] if foo.is_Add and foo.args[1].has(t): bar = foo.args[1] / t if not bar.has(t) and bar.has(sym.I): a = -(foo.args[0] * 2 * sym.pi * sym.I) / bar return const1 * sym.exp(-a * sf) * sym.Heaviside( sf * sym.sign(a)) # Punt and use SymPy. Should check for t**n, t**n * exp(-a * t), etc. return const * fourier_sympy(expr, t, sf) args = exps.args[0] foo = args / t if foo.has(t): # Have exp(a * t**n), SymPy might be able to handle this return const * fourier_sympy(expr, t, sf) if exps != 1 and foo.has(sym.I): return const1 * sym.DiracDelta(sf - foo / (sym.I * 2 * sym.pi)) return const * fourier_sympy(expr, t, sf)
def inverse_laplace_ratfun(expr, s, t): N, D, delay = Ratfun(expr, s).as_ratfun_delay() # The delay should be zero Q, M = N.div(D) result1 = sym.sympify(0) if Q: C = Q.all_coeffs() for n, c in enumerate(C): result1 += c * sym.diff(sym.DiracDelta(t), t, len(C) - n - 1) expr = M / D for factor in expr.as_ordered_factors(): if factor == sym.oo: return factor sexpr = Ratfun(expr, s) P = sexpr.poles() result2 = sym.sympify(0) P2 = P.copy() for p in P2: # Number of occurrences of the pole. N = P2[p] if N == 0: continue f = s - p if N == 1: r = sexpr.residue(p, P) pc = p.conjugate() if pc != p and pc in P: # Remove conjugate from poles and process pole with its # conjugate. Unfortunately, for symbolic expressions # we cannot tell if a quadratic has two real poles, # a repeat real pole, or a complex conjugate pair of poles. P2[pc] = 0 p_re = sym.re(p) p_im = sym.im(p) r_re = sym.re(r) r_im = sym.im(r) et = sym.exp(p_re * t) result2 += 2 * r_re * et * sym.cos(p_im * t) result2 -= 2 * r_im * et * sym.sin(p_im * t) else: result2 += r * sym.exp(p * t) continue # Handle repeated poles. expr2 = expr * f**N for n in range(1, N + 1): m = N - n r = sym.limit(sym.diff(expr2, s, m), s, p) / sym.factorial(m) result2 += r * sym.exp(p * t) * t**(n - 1) # result1 is a sum of Dirac deltas and its derivatives so is known # to be causal. return result1, result2
def fourier_term(expr, t, f, inverse=False): const, expr = factor_const(expr, t) if expr.has(sym.Integral): return fourier_integral(expr, t, f, inverse) * const if isinstance(expr, AppliedUndef): return fourier_func(expr, t, f, inverse) * const # TODO add u(t) <--> delta(f) / 2 - j / (2 * pi * f) if expr.has(AppliedUndef): # Handle v(t), v(t) * y(t), 3 * v(t) / t etc. return fourier_function(expr, t, f, inverse) * const # Check for constant. if not expr.has(t): return expr * sym.DiracDelta(f) * const one = sym.S.One const1 = const other = one exps = one factors = expr.expand().as_ordered_factors() for factor in factors: if not factor.has(t): const1 *= factor else: if factor.is_Function and factor.func == sym.exp: exps *= factor else: other *= factor sf = -f if inverse else f if other != 1 and exps == 1: if other == t: return const1 * sym.I / (2 * sym.pi) * sym.DiracDelta(sf, 1) elif other == t**2: return -const1 / (2 * sym.pi)**2 * sym.DiracDelta(sf, 2) # TODO check for other powers of t... elif other == sym.sign(t): return const1 / (sym.I * sym.pi * sf) elif other == sym.sign(t) * t: return -const1 * 2 / (2 * sym.pi * f)**2 elif other == sym.Heaviside(t): return const1 / (sym.I * 2 * sym.pi * f) + const1 * sym.DiracDelta(sf) / 2 elif other == 1 / t: return -const1 * sym.I * sym.pi * sym.sign(sf) elif other == 1 / t**2: return -const1 * 2 * sym.pi**2 * sf * sym.sign(sf) elif other.is_Function and other.func == sym.Heaviside and other.args[0].has(t): # TODO, generalise use of similarity and shift theorems for other functions and expressions scale, shift = scale_shift(other.args[0], t) return (const1 / (sym.I * 2 * sym.pi * sf / scale) / abs(scale) + const1 * sym.DiracDelta(sf) / 2) * sym.exp(sym.I * 2 * sym.pi * sf /scale * shift) elif other == sym.Heaviside(t) * t: return -const1 / (2 * sym.pi * f)**2 + const1 * sym.I * sym.DiracDelta(sf, 1) / (4 * pi) elif other.is_Function and other.func == sinc and other.args[0].has(t): scale, shift = scale_shift(other.args[0], t) return const1 * rect(sf / scale) * sym.exp(sym.I * 2 * sym.pi * sf /scale * shift) / abs(scale) elif other.is_Function and other.func == rect and other.args[0].has(t): return const1 * sinc(sf / scale) * sym.exp(sym.I * 2 * sym.pi * sf /scale * shift) / abs(scale) # Sympy incorrectly gives exp(-a * t) instead of exp(-a * t) * # Heaviside(t) if other.is_Pow and other.args[1] == -1: foo = other.args[0] if foo.is_Add and foo.args[1].has(t): bar = foo.args[1] / t if not bar.has(t) and bar.has(sym.I): a = -(foo.args[0] * 2 * sym.pi * sym.I) / bar return const1 * sym.exp(-a * sf) * sym.Heaviside(sf * sym.sign(a)) if expr == t * sym.DiracDelta(t, 1): return const * sf / (-sym.I * 2 * sym.pi) # Punt and use SymPy. Should check for t**n, t**n * exp(-a * t), etc. return const * fourier_sympy(expr, t, sf) args = exps.args[0] foo = args / t if foo.has(t): # Have exp(a * t**n), SymPy might be able to handle this return const * fourier_sympy(expr, t, sf) if exps != 1 and foo.has(sym.I): return const1 * sym.DiracDelta(sf - foo / (sym.I * 2 * sym.pi)) return const * fourier_sympy(expr, t, sf)