具有2个节点和RK45的质量弹簧系统的不稳定性

时间:2019-07-09 12:22:52

标签: python numpy scipy mass

我想对具有许多节点的质量弹簧系统的变形进行建模。在某些情况下,我会遇到不稳定的问题。

在此示例中,我模拟了重力对1kg节点的影响。

当我的节点0处于0.,0.,0。位置,而我的节点1处于1.,1.,1位置时,一切工作正常,并且弹簧的效果是连贯的。

当我的节点0处于位置0.,1.,0且我的节点1处于位置0.,0.,0时,结果发散。

我不明白为什么在相似的条件下仅由于节点位置而获得不同的结果。我使用求解器不对吗?还是我对弹簧力的计算是错误的?我尝试了经典的循环循环和矢量化方式,结果是相同的。

import numpy as np
from scipy.spatial.distance import cdist
import matplotlib.pyplot as plt
import scipy.integrate

X = np.array([[0., 0., 0.], # 0
             [1., 1., 1.]]) # 1

edges = np.array([[0, 1]])

W = np.array([[0, 1],
              [1, 0]])

d = cdist(X, X, "euclidean")

mass = 1 * np.ones(X.shape[0])
mass[0] = np.inf
mass[1] = 1
Force = np.zeros((X.shape[0], 3))
Force[1, 1] = 9.81
N = X.shape[0]

dt = 0.1
T = int(1e4)

k = 5


def compute_F_spring_vec(X, W, di):
    d_inv = np.reciprocal(cdist(X, X, "euclidean"))
    d_inv[np.arange(np.shape(d_inv)[0]),np.arange(np.shape(d_inv)[0])] = 0
    op1 = np.dot(W, X)
    op2 = X * np.repeat(np.sum(W, axis=1), 3).reshape(X.shape)
    op3 = np.dot(W * di * d_inv, X)
    op4 = X * np.repeat(np.sum(W * di * d_inv, axis=1), 3).reshape(X.shape)
    F_spring = - k * (-op1 + op2 + op3 - op4)

    return F_spring


def compute_F_spring(X, W, d):
    F_spring = []
    for i in range(X.shape[0]):
        F_i = np.zeros(3)
        for j in range(X.shape[0]):
            if W[i,j]:
                F_i += -k * (np.linalg.norm(X[i, :] - X[j, :]) - d[i, j]) * (X[i, :] - X[j, :])/np.linalg.norm(X[i, :] - X[j, :])

        F_spring.append(F_i)

    return F_spring

def fun(t, X):
    X = X.reshape((int(X.shape[0]/3), 3))
    F_spring = compute_F_spring_vec(X, W, d)
    F = F_spring + Force
    a = F / mass[:, np.newaxis]

    X = X + a*t
    return X.ravel()

solver = scipy.integrate.RK45(fun, 0, X.ravel(), t_bound=100, rtol=0.001, vectorized=True)

Ylast = np.inf
X1 = []

while solver.status == 'running' and solver.t < 10:
    error = solver.step()
    X1.append([solver.y[4], solver.t, solver.y[3], solver.y[5]])

    if (np.abs(X1[-1][0] - Ylast))/np.abs(Ylast) < 1e-6:
        break
    else:
        Ylast = X1[-1][0]

更加精确:

X包含所有节点的位置x,y,z。 边是每对节点之间的键。由此我可以得到连通性矩阵W。1是一个键,0不是。

d表示所有节点之间的欧式距离。

0 个答案:

没有答案