我想对具有许多节点的质量弹簧系统的变形进行建模。在某些情况下,我会遇到不稳定的问题。
在此示例中,我模拟了重力对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表示所有节点之间的欧式距离。