2

那里的大师:

航天器运动建模的微分方程可以用一组加速度项来描述:

d2r/dt2 =  a0 + a1 + a2 + ... + an

通常 a0 是物体的质点加速度 (a0 = -mu * r/r^3);“高阶”术语可能是由于其他行星、太阳辐射压力、推力等。

我正在实现一组旨在在这种系统上工作的算法。我将从 Python 开始进行设计和原型制作,然后我将转向 C++ 或 Fortran 95。

我想设计一个类(或元类),它允许我为给定实例指定不同的加速项,类似于:

# please notice this is meant as "pseudo-code"
def some_acceleration(t):
    return (1*t, 2*t, 3*t)

def some_other_acceleration(t):
    return (4*t, 5*t, 6*t)

S = Spacecraft()
S.Acceleration += someacceleration + some_other_acceleration

在这种情况下,实例 S 将默认为,例如,两个加速项,我将添加我想要的其他两个项:some accelerationsome_other_acceleration; 他们返回一个向量(这里表示为一个三元组)。请注意,在我的“实现”中,我重载了+运算符。

这样,算法将为抽象的“航天器”设计,所有实际力场都将根据具体情况提供,使我能够使用简化模型、比较建模方法等。

你将如何实现一个类或元类来处理这个问题?

对于这个相当冗长且解释不清的问题,我深表歉意,但我的大脑有点模糊。

谢谢。

4

4 回答 4

2

PyDSTool允许您将具有空间或物理意义的“组件”以及与之相关的数学表达式构建成更大的组件,这些组件知道如何总结事物等。结果是一种使用符号以模块化方式指定微分方程的方法工具,然后 PyDSTool 将自动创建 C 代码以使用快速集成器模拟系统。在使用 C 和 Fortran 进行“繁重的工作”之前,无需将 python 仅视为一个缓慢的原型设计步骤。一旦您完全指定了问题,PyDSTool 已经将所有内容(包括您定义的结果向量场)下移到 C 级别。

您的二阶 DE 示例与包含多种离子通道的生物细胞膜上的电位差的“电流平衡”一阶方程非常相似。根据基尔霍夫电流定律,pd 的变化率为

dV/dt = 1/memb_capacitance *(电流总和)

PyDSTool/tests/ModelSpec_tutorial_HH.py中的示例是捆绑在包中的几个示例之一,它从模块化规范组件(您继承以创建自己的ModelSpec类 - 例如物理中的“point_mass”)为膜构建模型环境),并使用类似宏的规范将最终 DE 定义为添加到“膜”组件的“离子通道”组件中存在的任何电流的总和。求和是在makeSoma函数中定义的,只需使用诸如“for(channel,current,+)/C”之类的语句,您可以直接在代码中使用它。

希望这可以帮助。如果是这样,请随时通过 sourceforge 上的帮助论坛询问我(PyDSTool 的作者)是否需要更多帮助来启动它。

于 2011-07-30T21:25:50.937 回答
1

对于那些想避免使用 numpy 并在纯 python 中执行此操作的人,这可能会给您一些好主意。我敢肯定这个小短剧也有缺点和缺陷。"operator" 模块加速了你的数学计算,因为它们是用 c 函数完成的:

from operator import sub, add, iadd, mul
import copy

class Acceleration(object):
   def __init__(self, x, y, z):
      super(Acceleration, self).__init__()
      self.accel = [x, y , z]
      self.dimensions = len(self.accel)

   @property
   def x(self):
      return self.accel[0]

   @x.setter
   def x(self, val):
      self.accel[0] = val


   @property
   def y(self):
      return self.accel[1]

   @y.setter
   def y(self, val):
      self.accel[1] = val

   @property
   def z(self):
      return self.accel[2]

   @z.setter
   def z(self, val):
      self.accel[2] = val

   def __iadd__(self, other):
      for x in xrange(self.dimensions):
         self.accel[x] = iadd(self.accel[x], other.accel[x])
      return self

   def __add__(self, other):
      newAccel = copy.deepcopy(self)
      newAccel += other
      return newAccel

   def __str__(self):
      return "Acceleration(%s, %s, %s)" % (self.accel[0], self.accel[1], self.accel[2])

   def getVelocity(self, deltaTime):
      return Velocity(mul(self.accel[0], deltaTime), mul(self.accel[1], deltaTime), mul(self.accel[2], deltaTime))

class Velocity(object):
   def __init__(self, x, y, z):
      super(Velocity, self).__init__()
      self.x = x
      self.y = y
      self.z = z

   def __str__(self):
      return "Velocity(%s, %s, %s)" % (self.x, self.y, self.z)

if __name__ == "__main__":
   accel = Acceleration(1.1234, 2.1234, 3.1234)
   accel += Acceleration(1, 1, 1)
   print accel

   accels = []
   for x in xrange(10):
      accel += Acceleration(1.1234, 2.1234, 3.1234)

   vel = accel.getVelocity(2)
   print "Velocity of object with acceleration %s after one second:" % (accel)
   print vel

打印以下内容:

加速度(2.1234、3.1234、4.1234)

加速度物体的速度 Acceleration(13.3574, 24.3574, 35.3574) 一秒后: Velocity(26.7148, 48.7148, 70.7148)

你可以得到更快的计算:

def getFancyVelocity(self, deltaTime):
   from itertools import repeat
   x, y, z = map(mul, self.accel, repeat(deltaTime, self.dimensions))
   return Velocity(x, y, z)
于 2010-01-04T18:28:40.380 回答
1

您是否在问如何为航天器类存储任意数量的加速度源?

你不能只使用一组函数吗?(使用 C++ 时的函数指针)

IE:

#pseudo Python
class Spacecraft
    terms = []
    def accelerate(t):
       a = (0,0,0)
       for func in terms:
         a+= func(t)


s = Spacecraft
s.terms.append(some_acceleration)
s.terms.append(some_other_acceleration)
ac = s.accelerate(t)
于 2010-01-21T02:35:56.910 回答
0

我会改用一些可以处理向量的库(在 python 中,尝试 numpy)并将加速度表示为向量。然后,您不会重新发明轮子,+ 运算符可以按照您的意愿工作。如果我误解了您的问题,请纠正我。

于 2010-01-04T17:50:39.237 回答