如何在OpenMDAO组件之间传递字符串值?

时间:2019-05-03 11:06:10

标签: string openmdao

我希望能够在组件之间传递字符串值。在最新版本的OpenMDAO中有可能吗?在将来的版本中有可能吗?

如果我理解正确,那么在早期版本的带有传递对象的OpenMDAO(V <= 1)中支持字符串的传递。当前,我使用一种解决方法,将工具的字符串输入和输出写入单独的文件,并在需要时从这些文件中获取。然后,这不在OpenMDAO模型之内。

这是一个小示例,说明如果可以将字符串用作输入和输出,将支持的模型类型。当然,这只是一个演示案例。

from openmdao.core.explicitcomponent import ExplicitComponent
from openmdao.core.group import Group
from openmdao.core.indepvarcomp import IndepVarComp
from openmdao.core.problem import Problem
from openmdao.devtools.problem_viewer.problem_viewer import view_model


class PreProcessor(ExplicitComponent):

    def setup(self):
        self.add_input('a', val=0.)

        self.add_output('para_shape', val='hill')

    def compute(self, inputs, outputs):
        if inputs['a'] <= 0.:
            outputs['para_shape'] = 'hill'
        else:
            outputs['para_shape'] = 'canyon'


class Parabola(ExplicitComponent):

    def setup(self):
        self.add_input('x', val=0.)
        self.add_input('para_shape', val='hill')

        self.add_output('y', val=0.)

    def compute(self, inputs, outputs):
        if inputs['para_shape'] == 'hill':
            outputs['y'] = -inputs['x']**2
        elif inputs['para_shape'] == 'canyon':
            outputs['y'] = inputs['x']**2
        else:
            raise IOError('Invalid "para_shape" value "{}" provided.'.format(inputs['para_shape']))


if __name__ == "__main__":

    model = Group()
    ivc = IndepVarComp()
    ivc.add_output('a', 2.)
    ivc.add_output('x', 4.)
    model.add_subsystem('vars', ivc, promotes=['*'])
    model.add_subsystem('preprocessor', PreProcessor(), promotes=['*'])
    model.add_subsystem('parabola', Parabola(), promotes=['*'])

    prob = Problem(model)
    prob.setup()
    view_model(prob, outfile='n2_pass_by_object_example.html')

    prob.run_model()

如果运行此命令,我将得到ValueError的{​​{1}},这是可以预期的。我只是想知道是否有一种方法可以使could not convert string to float: hill保留为para_shape的字符串输出,而保留PreProcessor的字符串输入。

除此以外,在我的情况下,很方便地传递字符串,我认为当使用支持离散值的优化算法(例如遗传算法)时,这也可能会有所帮助。在这些算法中,Parabola可以是一个设计变量,可能的值为para_shapehill。在幕后,这样的字符串变量可能会映射为整数值,例如canyon

总而言之,我的问题是:将为OpenMDAO 2实现传递对象(或类似的功能,使我能够定义字符串输入/输出)吗?

1 个答案:

答案 0 :(得分:1)

好消息是,当前版本的OpenMDAO确实支持离散变量。我已经更新了您的示例,以使用当前语法声明离散变量并将其传递给计算函数。基本上,更改是您必须使用add_discrete_inputadd_discrete_output声明离散变量。另外,您必须将discrete_inputsdiscrete_outputs作为参数添加到compute函数中,因此新版本看起来像:def compute(self, inputs, outputs, discrete_inputs, discrete_outputs)。还要注意,如果您的组件碰巧使用了其他函数,例如compute_partialscompute_jacvec_product和其他函数,则还需要其他离散的args。

坏消息是您的示例发现了view_model中的错误。看来view_model当前不正确支持离散变量。我在错误跟踪器中放入了一个描述问题的错误,因此希望我们尽快予以解决。

from openmdao.core.explicitcomponent import ExplicitComponent
from openmdao.core.group import Group
from openmdao.core.indepvarcomp import IndepVarComp
from openmdao.core.problem import Problem
from openmdao.devtools.problem_viewer.problem_viewer import view_model


class PreProcessor(ExplicitComponent):

    def setup(self):
        self.add_input('a', val=0.)

        self.add_discrete_output('para_shape', val='hill')

    def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
        if inputs['a'] <= 0.:
            discrete_outputs['para_shape'] = 'hill'
        else:
            discrete_outputs['para_shape'] = 'canyon'


class Parabola(ExplicitComponent):

    def setup(self):
        self.add_input('x', val=0.)
        self.add_discrete_input('para_shape', val='hill')

        self.add_output('y', val=0.)

    def compute(self, inputs, outputs, discrete_inputs, discrete_outputs):
        if discrete_inputs['para_shape'] == 'hill':
            outputs['y'] = -inputs['x']**2
        elif discrete_inputs['para_shape'] == 'canyon':
            outputs['y'] = inputs['x']**2
        else:
            raise IOError('Invalid "para_shape" value "{}" provided.'.format(inputs['para_shape']))


if __name__ == "__main__":

    model = Group()
    ivc = IndepVarComp()
    ivc.add_output('a', 2.)
    ivc.add_output('x', 4.)
    model.add_subsystem('vars', ivc, promotes=['*'])
    model.add_subsystem('preprocessor', PreProcessor(), promotes=['*'])
    model.add_subsystem('parabola', Parabola(), promotes=['*'])

    prob = Problem(model)
    prob.setup()
    view_model(prob, outfile='n2_pass_by_object_example.html')
    prob.run_model()