OpenMDAO:当其他子系统串行运行时,如何对特定子系统使用并行处理



我正在使用基于OpenMDAO的脚本进行静态气动弹性分析。我正在尝试调整我的脚本,使其在超级计算机上运行。

MDA循环包括几个组件,包括一个通常在mpirun -np 24 python runScript.py终端中运行的CFD求解器和一个通常与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):
...

事先非常感谢您的帮助!

如果没有更多细节,很难给你一个准确的答案。然而,听起来您有一个组件正在进行子流程调用,以尝试在MPI下运行CFD,而OpenMDAO模型本身则在顶部串行运行。

这通常是OpenMDAO的错误方法。框架本身具有MPI意识,组件可以声明分布式输入/输出。分布式IO的文档提供了一些不错的例子

我还建议您查看Mphys库,它建立在OpenMDAO之上,有很多航空结构示例可供使用。

您可以考虑只使用python aeroelastic_mda.py串行运行顶级脚本,并修改Popen调用以使用mpirun运行子流程,例如Popen(['mpirun', '-np', '24', 'nast20212', 'nastran_static_alpha_c.bdf'])。您还可以修改您的顶级脚本以接受命令行参数,从而指定要用于调用nastran和Dafoam的进程数。

我最终解决了我的问题,用ShellProc(openmdao.utils.shell_proc(函数替换了Popen。由于某些原因,Popen在与mpirun命令一起使用时无法正常工作。

最新更新