OpenMDAO: как использовать параллельную обработку для конкретной подсистемы, в то время как другие работают последовательно?

Я выполняю статический аэроупругий анализ, используя скрипт на основе OpenMDAO. Я пытаюсь адаптировать свой скрипт для запуска на суперкомпьютере.

Цикл MDA включает в себя несколько компонентов, в том числе решатель CFD, который обычно запускается в терминале с помощью mpirun -np 24 python runScript.py, и структурный решатель, который обычно запускается в терминале с помощью nast20212 nastran_static_alpha_c.bdf.

Чтобы запустить CFD в параллельном режиме в моем основном скрипте, мне нужно запустить его с помощью mpirun -np 24 python aeroelastic_mda.py.

Проблема в том, что когда я это делаю, скрипт пытается запустить все компоненты в параллельном режиме. Однако мне нужно было только запустить мой CFD-решатель для работы на нескольких узлах, в то время как другие компоненты работают в последовательном режиме.

Я просмотрел документацию OpenMDAO и другие сообщения, но не нашел информации по своей проблеме.

Ниже приведен краткий обзор моего сценария OpenMDAO, который я запускаю с mpirun -np 24 python aeroelastic_mda.py.

#Importing necessary modules
...  
if __name__ == "__main__":
    #Problem parameters
    Sw = 383.689555/2 #Wing reference surface
    V = 295.0 #Airspeed
    rho_a = 1.17 #Air density
    ... #Some other parameters
   
    root = Problem()

    #Add independent variables
    root.model.add_subsystem('wing_area', IndepVarComp('Sw', Sw), promotes=['*'])
    root.model.add_subsystem('airspeed', IndepVarComp('V', V), promotes=['*'])
    root.model.add_subsystem('air_density', IndepVarComp('rho_a', rho_a), promotes=['*'])
    ... #Some other independent variables

    mda = Group()

    #Add disciplines to the group

    # Displacement transfer: 
    # Inputs -> Displacements at structural nodes
    # Outputs -> Displacements to be applied to aerodynamic nodes 
    # Simple matrix product
    mda.add_subsystem('displacement_transfer', DisplacementTransfer(), promotes=['*'])

    # Aerodynamic solver
    mda.add_subsystem('aerodynamics', Dafoam(), promotes=['*'])

    # Load transfer
    # Inputs -> Forces at aerodynamic nodes
    # Outputs -> Forces to be applied to structural nodes 
    # Simple matrix product
    mda.add_subsystem('load_transfer', LoadTransfer(), promotes=['*'])
   
    # Structural solver
    mda.add_subsystem('structures', NastranStatic(), promotes=['*'])

    root.model.add_subsystem('mda_group', mda, promotes=['*'])

    mda.nonlinear_solver = NonlinearBlockGS()
    mda.nonlinear_solver.options['rtol'] = 1.e-3
    mda.nonlinear_solver.options['use_aitken'] = True

    mda.linear_solver = ScipyKrylov()
    root.linear_solver = ScipyKrylov()

    root.setup()
    root.run_model()

Также вот упрощенный вид моего аэродинамического компонента:

#Importing necessary modules
...
class Dafoam(ExplicitComponent):
    ... #Some constants
    
    def initialize(self):
        ... #Declaring options

    def setup(self):
        ... #Declaring inputs
        ... #Declaring outputs

    def compute(self, inputs, outputs):
        #Generate current deformed shape
        self.create_current_geom(inputs, outputs)

        #Generate the input file for Dafoam from current geometry and flow conditions
        self.create_input_file(inputs, outputs)

        # Run DAFoam
        p = Popen(['python', 'runScript.py'])
        p.wait()

        # Parse the output file from the external code    
        ...

    def create_current_geom(self, inputs, outputs):
    ...
    #Method that creates the Dafoam input file runScript.py
    def create_input_file(self, inputs, outputs):
    ...
    def get_forces(self, inputs, outputs):
    ...
    def get_aero_coeff(self, inputs, outputs):     
    ...

Также вот упрощенный вид моего структурного компонента:

#Importing necessary modules
...  
class NastranStatic(ExplicitComponent):
    ... #Some constants
    
    def initialize(self):
        ... #Declaring options

    def setup(self):
        ... #Declaring inputs
        ... #Declaring outputs

    def compute(self, inputs, outputs):
        # Generate the input file for Nastran
        self.create_input_file(inputs, outputs)

        # Run MSC Nastran
        p = Popen(['nast20212', 'nastran_static_alpha_c.bdf'])
        p.wait()

        # Parse the output file from the external code and set output values
        ...

    def create_input_file(self, inputs, outputs):
    ...
    def get_output_data(self, inputs, outputs):
    ...

Заранее большое спасибо за вашу помощь!

Из вашего вопроса не ясно на 100%, но похоже, что вы пытаетесь использовать компонент OpenMDAO, который вызывает вызов подпроцесса для запуска вашего aero_analysis.py. Если это так, то это неправильный подход к использованию MPI. Чтобы дать вам реальный ответ, не могли бы вы привести игрушечный пример, который, по крайней мере, показывает структуру ваших компонентов и модели, а также любые соответствующие команды запуска, которые вы используете?

Justin Gray 29.09.2022 00:23

@JustinGray спасибо за ответ. Я добавил упрощенные виды моего основного скрипта OpenMDAO, аэродинамических и конструктивных компонентов. Когда я запускаю основной скрипт в MPI, CFD-решатель успешно работает в MPI, но основной скрипт также пытается запустить структурный решатель в MPI, даже если, как я знаю, он не поддерживает MPI. Пожалуйста, сообщите мне, если вам нужна дополнительная информация.

yll 29.09.2022 14:58
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
105
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Без подробностей сложно дать точный ответ. Тем не менее, похоже, что у вас есть компонент, выполняющий вызов подпроцесса, чтобы попытаться запустить CFD под MPI, в то время как сама модель OpenMDAO запускается последовательно сверху.

Вообще говоря, это неправильный подход к OpenMDAO. Сама структура поддерживает MPI, и компоненты могут объявлять распределенные входы/выходы. Документы по распределенному вводу-выводу дают несколько достойных примеров, на которые стоит обратить внимание.

Я также рекомендую вам ознакомиться с библиотекой Mphys, которая построена на основе OpenMDAO и содержит множество примеров аэроструктур для работы.

Вы можете рассмотреть возможность последовательного запуска скрипта верхнего уровня только с помощью python aeroelastic_mda.py и изменить вызовы Popen для запуска подпроцессов с помощью mpirun, например Popen(['mpirun', '-np', '24', 'nast20212', 'nastran_static_alpha_c.bdf']). Вы также можете изменить свой сценарий верхнего уровня, чтобы он принимал аргументы командной строки, чтобы указать количество процессов, которые вы хотите использовать с вашими вызовами nastran и Dafoam.

@BretNeylor спасибо за ответ. Это была моя первая идея, но по какой-то причине Popen(['mpirun', '-np', '24', 'python','runScript.py']) не работает в моей среде OpenMDAO. Код компонента просто не запускается и сразу завершается.

yll 29.09.2022 16:18

Вы получили сообщение об ошибке, когда пытались это сделать? Если да, то не могли бы вы опубликовать это? Я только что попробовал это с помощью простого скрипта Python и нижнего скрипта, и он работал нормально.

Bret Naylor 29.09.2022 17:30

Нет, к сожалению, я не получаю конкретного сообщения. Я пытался сделать это с помощью простого скрипта, как и вы, он работал нормально, пока я не импортировал API OpenMDAO. Может быть, вы можете попробовать добавить его в свой сценарий, чтобы посмотреть, сможете ли вы воспроизвести проблему?

yll 29.09.2022 20:30
Ответ принят как подходящий

В конце концов я решил свою проблему, заменив Popen функцией ShellProc (openmdao.utils.shell_proc). По какой-то причине Popen не работал должным образом при использовании с командой mpirun.

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