Дизайн класса или метакласса для двигателя астродинамики - PullRequest
2 голосов
/ 04 января 2010

Гуру там:

Дифференциальные уравнения для моделирования движения космического корабля могут быть описаны в терминах набора членов ускорения:

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 acceleration и some_other_acceleration; они возвращают вектор (здесь представлен как триплет). Обратите внимание, что в моей «реализации» я перегружен оператор +.

Таким образом, алгоритмы будут разработаны для абстрактного "космического корабля", и все фактические силовые поля будут предоставляться в каждом конкретном случае, что позволяет мне работать с упрощенными моделями, сравнивать методологии моделирования и т. Д.

Как бы вы реализовали класс или метакласс для обработки этого?

Я прошу прощения за довольно многословный и неясный вопрос, но он немного размыт в моем мозгу.

Спасибо.

Ответы [ 4 ]

2 голосов
/ 31 июля 2011

PyDSTool позволяет создавать «компоненты», которые имеют пространственное или физическое значение и имеют связанные с ними математические выражения, в более крупные компоненты, которые знают, как суммировать вещи и т. Д. В результате получается способ задайте дифференциальные уравнения модульным способом, используя символические инструменты, а затем PyDSTool автоматически создаст код C для моделирования системы с использованием быстрых интеграторов. Нет необходимости рассматривать Python как медленный шаг прототипирования, прежде чем выполнять «тяжелую работу» в C и Fortran. PyDSTool уже перемещает все, включая результирующее векторное поле, которое вы определили, до уровня C, как только вы полностью определили проблему.

Ваш пример для DE второго порядка очень похож на уравнение первого порядка «текущего баланса» для разности потенциалов через биологическую клеточную мембрану, которая содержит несколько типов ионных каналов. Согласно действующему закону Кирхгофа, скорость изменения p.d. есть

dV / dt = 1 / мембранная емкость * (сумма токов)

Пример в PyDSTool / tests / ModelSpec_tutorial_HH.py является одним из нескольких в комплекте, который создает модель для мембраны из компонентов модульной спецификации (класс ModelSpec , из которого вы наследуете, чтобы создать свой собственный (например, «point_mass» в физической среде), и используете макроподобную спецификацию для определения конечного DE как суммы любых токов, присутствующих в компонентах «ионного канала», добавленных к «мембране» " составная часть. Суммирование определяется в функции makeSoma , просто с помощью такого выражения, как 'for (channel, current, +) / C', которое вы можете просто использовать непосредственно в своем коде.

Надеюсь, это поможет. Если это так, не стесняйтесь спрашивать меня (автора PyDSTool) через справочный форум на sourceforge, если вам нужна дополнительная помощь для начала работы.

1 голос
/ 04 января 2010

Для тех, кто хотел бы избежать NumPy и сделать это на чистом питоне, это может дать вам несколько хороших идей. Я уверен, что у этой маленькой пародии есть недостатки и недостатки. Модуль "оператор" ускоряет ваши математические вычисления, поскольку они выполняются с помощью функций 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)

Скорость объекта с ускорением Ускорение (13,3574, 24,3574, 35,3574) через одну секунду: Скорость (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)
1 голос
/ 21 января 2010

Вы спрашиваете, как хранить произвольное количество источников ускорения для класса космического корабля?

Разве вы не можете просто использовать массив функций? (Указатели на функции при переходе на c ++)

т.е:

#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)
0 голосов
/ 04 января 2010

Я бы использовал вместо этого некоторую библиотеку, которая может работать с векторами (в python, попробуйте numpy) и представлять ускорение как вектор. Тогда вы не изобретаете велосипед, оператор + работает так, как вы хотели. Пожалуйста, поправьте меня, если я неправильно понял вашу проблему.

...