【问题标题】:Python. How to constrain the particles to only move on the surface of the sphere?Python。如何约束粒子只在球体表面移动?
【发布时间】:2022-11-11 06:35:02
【问题描述】:

我正在使用 vpython 来模拟球体上的粒子在被位于球体下方板上的其他粒子排斥时的运动。我使用以下代码计算每个力。

  for i in range(len(charOS)): #COS
    for j in range(len(charges_on_plate)): #COP
      d = sqrt((charOS[i].pos.x - charges_on_plate[j].pos.x)**2 + (charOS[i].pos.y - charges_on_plate[j].pos.y)**2 + (charOS[i].pos.z - charges_on_plate[j].pos.z)**2)
      newFx = (con/(d**2)) * np.cos(np.arctan((charOS[i].pos.y - charges_on_plate[j].pos.y)/(charOS[i].pos.x - charges_on_plate[j].pos.x)))
      newFy = (con/(d**2)) * np.sin(np.arctan((charOS[i].pos.y - charges_on_plate[j].pos.y)/(charOS[i].pos.x - charges_on_plate[j].pos.x)))
      newFz = (con/(d**2)) * np.sin(np.arcsin((charOS[i].pos.z - charges_on_plate[j].pos.z)/(d)))
      Fx = Fx + newFx
      Fy = Fy + newFy
      Fz = Fz + newFz
    list_Fx.append(Fx)
    list_Fy.append(Fy)
    list_Fz.append(Fz)

然后我想根据x, y, z军队。但它们必须被限制在球体的表面。我已经开发了这段代码,但似乎效果不佳。

我的约束代码:

  for i in range(len(charOS)):
    if charOS[i].pos.x + radius/60 >= radius - dr*1.01 or charOS[i].pos.x + radius/60 <= -1*radius + dr*1.01:
      charOS[i].velocity = S_C_V*vector(list_Fx[i]*0, list_Fy[i], list_Fz[i])
      if charOS[i].pos.y + radius/60 >= posvec1.y - dr*1.01 or charOS[i].pos.y + radius/60 <= dr*1.01 + posvec2.y:
        charOS[i].velocity = S_C_V*vector(list_Fx[i]*0, list_Fy[i]*0, list_Fz[i])
        if charOS[i].pos.z + radius/60 >= radius - dr*1.01 or charOS[i].pos.z + radius/60 <= dr*1.01 + -1*radius:
          charOS[i].velocity = S_C_V*vector(list_Fx[i]*0, list_Fy[i]*0, list_Fz[i]*0)
    else:
      charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i], list_Fz[i])
      if charOS[i].pos.y + radius/60 >= posvec1.y - dr*1.01 or charOS[i].pos.y + radius/60 <= dr*1.01 + posvec2.y:
        charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i]*0, list_Fz[i])
        if charOS[i].pos.z + radius/60 >= radius - dr*1.01 or charOS[i].pos.z + radius/60 <= dr*1.01 + -1*radius:
          charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i]*0, list_Fz[i]*0)
      else:
        charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i], list_Fz[i])
        if charOS[i].pos.z + radius/60 >= radius - dr*1.01 or charOS[i].pos.z + radius/60 <= dr*1.01 + -1*radius:
          charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i], list_Fz[i]*0)
        else:
          charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i], list_Fz[i])
    charOS[i].pos = charOS[i].pos + charOS[i].velocity*deltat
    

我知道它可能相当混乱,但我真的不知道如何优化它并获得所需的结果,感谢您的建议!

【问题讨论】:

    标签: python for-loop vector simulation physics


    【解决方案1】:

    我终于找到了答案。事实上,这相当容易,首先我允许在球体半径之外计算新位置,然后我可以通过将每个向量相除来执行向量归一化x, y, z通过向量的大小。这给出了一个单位向量,然后最后将单位向量乘以所需球体的半径。代码:

      for i in range(len(charOS)):
        charOS[i].velocity = S_C_V*vector(list_Fx[i], list_Fy[i], list_Fz[i])
        charOS[i].pos = charOS[i].pos + charOS[i].velocity*deltat
        point_vector = charOS[i].pos/mag(charOS[i].pos)
        charOS[i].pos = point_vector * radius
    

    计算比我之前的尝试要短得多,而且相当简单。 :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多