Как интегрировать оценку дискретного времени в компоненты OpenMDAO?

Я пытаюсь ознакомиться с OpenMDAO. Одна вещь, которую мне трудно понять, это то, как интегрированные переменные/переменные состояния работают в отдельных компонентах OpenMDAO. Я думаю, что это очень важно, и я хочу понять основы.

Допустим, у меня есть ракета с постоянной тягой и изменяющейся массой, и я хочу смоделировать первые 10 секунд полета с дискретным временем и временным шагом 0,1 секунды. Допустим, изменяющаяся масса также является функцией времени, но также представьте, что это сложная переменная, зависящая от многих вещей, поэтому мы хотим, чтобы она вычислялась в другом компоненте и просто была входом для этого компонента.

-Как гарантировать, что Масса обновляется при дискретном временном вычислении Скорости, находясь в другом компоненте?

Приведенный ниже код является посредственной попыткой того, что я попытался бы решить в этом примере проблемы, но теперь я уверен, что Mass — это простой статический ввод, в то время как он должен изменяться в какой-то произвольной зависимости от времени. (Давайте предположим, что тяга постоянна)

from openmdao.api import ExplicitComponent

class VelocityComponent(ExplicitComponent):

    def setup(self):
        self.add_input('T', desc='Propulsion Thrust')
        self.add_input('M', desc='Instanteneous Mass')\

        self.add_output('v', desc='Satellite Velocity')

        self.declare_partials('*','*')

    def compute(self, inputs, outputs)

        v = 10                          #some initial velocity value
        t = 0                           #initial time value
        tstep = 0.1
        tend = 10

        for i in range(0,tend/tstep):
            a = inputs['T']/inputs['M'] #calculate acceleration  
            v += a                      #update velocity
            t += tstep                  #next time step 

        outputs['v'] = v 

скорость v должна интегрироваться с зависящим от времени ускорением a, а не с постоянным ускорением.

PS: Поскольку я новичок во всем этом, но готов учиться, любые советы по ресурсам, которые могут помочь начинающим, таким как я, с OpenMDAO, очень ценятся.

PSPS: я прочитал Руководство для начинающих и опытных пользователей документации OpenMDAO, но не смог найти пример с интегрированными переменными. В старой документации есть пример система двигателя и трансмиссии, и его компонент движка действительно включает переменные состояния и некоторые отдельные шаги интеграции, но он использует более старую версию OpenMDAO, и я не знаю, как это будет работать в более новой версии (если я вообще понимаю старый правильно)

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
153
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это обсуждение интеграции ODE, и вы выбрали довольно сложную тему, потому что 1) существует множество различных способов выполнить интеграцию (например, явный Эйлер, RK4, BDF...) 2) проведение аналитических производных через интегрирование по времени очень сложно.

для № 2 корень трудности именно в той проблеме, которую вы определили. Вы не можете использовать простую структуру цикла for внутри одного компонента, если вы также хотите построить ОДУ из набора различных компонентов, организованных в группу.

Хорошей новостью является то, что уже написана библиотека, которая выполняет всю интеграцию по времени за вас: Димос. По состоянию на апрель 2019 года эта библиотека находится в стадии активной разработки самой командой OpenMDAO и все еще подвергается изменениям API некоторых режимов и добавлению функций. Несмотря на несколько плавные API, я бы порекомендовал вам взглянуть на приведенные там примеры. Для сложных задач это лучший выбор.

Однако вы можете выполнить простую интеграцию Эйлера с временным шагом без дополнительной библиотеки. Хитрость заключается в том, что вы штампуете один экземпляр вашего ОДУ для каждого временного шага и передаете новое состояние по цепочке от одного экземпляра к другому. Вот очень простой пример падающего объекта под действием постоянной гравитации:

from openmdao.api import IndepVarComp, Problem, ExplicitComponent


class Cannonball(ExplicitComponent): 

    def initialize(self): 

        self.options.declare('delta_t', default=0.1)

    def setup(self): 

        self.add_input('Yi', units='m',   desc='position at the start of the time-step')
        self.add_input('Vi', units='m/s', desc='velocity at the start of the time-step')

        self.add_output('Ye', units='m',   desc='position at the end of the time-step')
        self.add_output('Ve', units='m/s', desc='velocity at the end of the time-step')

        self.declare_partials(of='*', wrt='*', method='cs')


    def compute(self, inputs, outputs): 

        dt = self.options['delta_t']

        outputs['Ve'] = 9.81 * dt + inputs['Vi']
        outputs['Ye'] = 0.5 * 9.81 * dt**2 + inputs['Vi'] * dt + inputs['Yi']


if __name__ == "__main__": 
    import numpy as np
    import matplotlib.pylab as plt

    N_TIMES = 10

    p = Problem()

    ivc = p.model.add_subsystem('init_conditions', IndepVarComp(), promotes=['*'])
    ivc.add_output('Y0', 100., units='m')
    ivc.add_output('V0', 0, units='m/s')

    p.model.connect('Y0', 't_0.Yi')
    p.model.connect('V0', 't_0.Vi')

    for i in range(N_TIMES): 
        p.model.add_subsystem(f't_{i}', Cannonball())


    for i in range(N_TIMES-1): 
        p.model.connect(f't_{i}.Ye', f't_{i+1}.Yi')
        p.model.connect(f't_{i}.Ve', f't_{i+1}.Vi')

    p.setup()

    p.run_model()


    # collect the data into an array for plotting
    Y = [p['Y0'],]
    V = [p['V0'],]
    for i in range(N_TIMES): 
        Y.append(p[f't_{i}.Ye'])
        V.append(p[f't_{i}.Ve'])

    times = np.arange(N_TIMES+1) * .01 # delta_t

    fig, ax = plt.subplots()
    ax.plot(times, Y)
    ax.set_ylabel('velocity (m/s')
    ax.set_xlabel('time (s)')

    plt.show()

Это даст временную структуру для вашей модели (сгенерированную с использованием Встроенный в OpenMDAO просмотрщик N2). n2 diagram

И вы можете видеть, что вы получаете ожидаемую квадратичную позицию по времени.

position with respect to time

Вы можете сделать более сложную интеграцию, закодировав другую схему ODE в этот компонент (например, RK4). Вы также можете написать более сложную группу, состоящую из нескольких компонентов, которая будет служить временным шагом, а затем отпечатать несколько копий этой группы.

Я хочу подчеркнуть, что, хотя приведенный выше пример хорош для понимания, это не очень эффективный способ выполнить интеграцию времени в OpenMDAO. Димос внутренне делает вещи совсем по-другому, работая с компонентами, которые векторизованы во времени для гораздо большей эффективности. Тем не менее, если вас действительно интересует самая простая схема временной интеграции в OpenMDAO... вот она.

Большое спасибо за быстрый и исчерпывающий ответ! Хотя я уверен, что это также принесет много новых, вы полностью ответили на мои вопросы. Очень ценю.

Ruben 02.04.2019 16:30

Другие вопросы по теме