通过Kanes方法模拟的摆的N体系统的时间段不正确

时间:2019-01-14 22:33:37

标签: python physics ode

我们可以使用Kane方法对具有任意质量和长度(see this)的n摆系统的运动方程进行积分。该程序的实现受到jakevdp的启发。但是,当我使用这种近似方法来找到伪时间段T(定义为n摆系统(即{{1})中每个摆的所有时间段的平均值时, },average(period(theta_1),...,period(theta_n)))作为T的函数的图在幅度方面似乎难以置信。

目的:可视化摆的数量n与整个系统的伪时间周期n之间的关系,其中T=2π/omega bar是所有角速度{{1}的平均值}。

以下实现定义和求解具有任意质量和长度的omega bar摆系统的运动方程(在这种情况下,我们将omega用于所有n)。这是m[i]=1i的初始值问题。

theta_1(0)=135,...,theta_n(0)=135

以上内容返回广义的物理坐标,即相对于垂直方向的每个摆线段的角位置theta_1'(0)=0,...,theta_n'(0)=0和速度# %matplotlib inline import matplotlib.pyplot as plt import numpy as np import pandas as pd from sympy import symbols from sympy.physics import mechanics from sympy import Dummy, lambdify from scipy.integrate import odeint def integrate_pendulum(n, times, initial_positions=135, initial_velocities=0, lengths=None, masses=1): """Integrate a multi-pendulum with `n` sections""" #------------------------------------------------- # Step 1: construct the pendulum model # Generalized coordinates and velocities # (in this case, angular positions & velocities of each mass) q = mechanics.dynamicsymbols('q:{0}'.format(n)) u = mechanics.dynamicsymbols('u:{0}'.format(n)) # mass and length m = symbols('m:{0}'.format(n)) l = symbols('l:{0}'.format(n)) # gravity and time symbols g, t = symbols('g,t') #-------------------------------------------------- # Step 2: build the model using Kane's Method # Create pivot point reference frame A = mechanics.ReferenceFrame('A') P = mechanics.Point('P') P.set_vel(A, 0) # lists to hold particles, forces, and kinetic ODEs # for each pendulum in the chain particles = [] forces = [] kinetic_odes = [] for i in range(n): # Create a reference frame following the i^th mass Ai = A.orientnew('A' + str(i), 'Axis', [q[i], A.z]) Ai.set_ang_vel(A, u[i] * A.z) # Create a point in this reference frame Pi = P.locatenew('P' + str(i), l[i] * Ai.x) Pi.v2pt_theory(P, A, Ai) # Create a new particle of mass m[i] at this point Pai = mechanics.Particle('Pa' + str(i), Pi, m[i]) particles.append(Pai) # Set forces & compute kinematic ODE forces.append((Pi, m[i] * g * A.x)) kinetic_odes.append(q[i].diff(t) - u[i]) P = Pi # Generate equations of motion KM = mechanics.KanesMethod(A, q_ind=q, u_ind=u, kd_eqs=kinetic_odes) fr, fr_star = KM.kanes_equations(particles, forces) #----------------------------------------------------- # Step 3: numerically evaluate equations and integrate # initial positions and velocities – assumed to be given in degrees y0 = np.deg2rad(np.concatenate([np.broadcast_to(initial_positions, n), np.broadcast_to(initial_velocities, n)])) # lengths and masses if lengths is None: lengths = np.ones(n) / n lengths = np.broadcast_to(lengths, n) masses = np.broadcast_to(masses, n) # Fixed parameters: gravitational constant, lengths, and masses parameters = [g] + list(l) + list(m) parameter_vals = [9.81] + list(lengths) + list(masses) # define symbols for unknown parameters unknowns = [Dummy() for i in q + u] unknown_dict = dict(zip(q + u, unknowns)) kds = KM.kindiffdict() # substitute unknown symbols for qdot terms mm_sym = KM.mass_matrix_full.subs(kds).subs(unknown_dict) fo_sym = KM.forcing_full.subs(kds).subs(unknown_dict) # create functions for numerical calculation mm_func = lambdify(unknowns + parameters, mm_sym) fo_func = lambdify(unknowns + parameters, fo_sym) # function which computes the derivatives of parameters def gradient(y, t, args): vals = np.concatenate((y, args)) sol = np.linalg.solve(mm_func(*vals), fo_func(*vals)) return np.array(sol).T[0] # ODE integration return odeint(gradient, y0, times, args=(parameter_vals,)) 。下面从广义坐标中提取theta坐标。

omega

然后,将摆数固定为(x,y),并使用以下方法确定伪时间段:

def get_xy_coords(p, lengths=None):
    """Get (x, y) coordinates from generalized coordinates p"""
    p = np.atleast_2d(p)
    n = p.shape[1] // 2
    if lengths is None:
        lengths = np.ones(n) / n
    zeros = np.zeros(p.shape[0])[:, None]
    x = np.hstack([zeros, lengths * np.sin(p[:, :n])])
    y = np.hstack([zeros, -lengths * np.cos(p[:, :n])])
    return np.cumsum(x, 1), np.cumsum(y, 1)

当我们绘制它时,我们得到n=10的以下图形: 但是,它应根据n = 10 nperiod = [] #Array containing pseudo-period for a system of `n` pendulums for i in range(1,n + 1): t = np.linspace(0, 10, 1000) p = integrate_pendulum(i, times=t) #x, y has first column of zeros x, y = get_xy_coords(p) r,s = np.shape(y) #Call method to find pseudo-period nperiod.append(computeperiod()) #Takes `j`, denoting `j`-th pendulum, as input and returns `theta_j` for all times where `1≤j≤n`. This information corresponds to the `j`-th column of the `y` matrix, transformed into polar coordinates. def theta(j): theta_j = [] for i in range(0, r): theta_j.append(math.acos(abs(y[i][j-1]-y[i][j]))) #We should technically divide by the length of the pendulum in `abs(.)` timenew = [i for i in range(1,r + 1)] graph_j = pd.Series(data=theta_j, index=timenew) #Returns array omega_j which is the numerical time derivative of all values contained in the `r x 1` array `theta_j`, i.e. the value of the `j`-th angle theta_j for all times return pd.Series(data=np.gradient(graph_j.values), index=graph_j.index) #Returns pseudo-time period using formula `T=2π/omega` def computeperiod(): series = [] for j in range(1,s): series.append(2 * math.pi/(theta(j).mean())) numberline = [i for i in range(1,s)] #Here s=n+1 timeperiod = pd.Series(data=series, index=numberline) return abs(timeperiod.mean()) print(nperiod) numbers = [i for i in range(len(nperiod))] finalperiods = pd.Series(data=nperiod, index=numbers) finalperiods.plot() 渐近地表现为n=10,其中O(n^(3/2))T(n) = 2 * π * n^(3/2)(l/g)^(1/2)如下。

此外,其幅度应减小大约g = 9.8的一个因子。因此,似乎这种方法显然有问题。

0 个答案:

没有答案