【问题标题】:Define variable in problem which is not used as input, and equals a previous input/output在问题中定义不用作输入且等于先前输入/输出的变量
【发布时间】:2021-08-17 12:53:18
【问题描述】:

我想定义一个变量,根据某些选项,该变量将等于先前的输出(就好像先前的输出有两个名称一样)或者将是新组件的输出。

一个简单的解决方案是在定义它的组件未实现时省略值的定义,但出于可读性/可追溯性的原因,我更愿意对其进行定义(以简化代码中的 if 语句,并将其作为时间序列输出提供)。

问题是在使用connect语句时,如果后续条件没有导致变量被用作另一个组件的输入,它会提供一个错误,指出它试图连接但变量不存在。

我使用一种链接语句 (LinkVarComp bellow) 进行了时间修复,它创建了一个输出等于输入的显式组件(以及一些其他的东西,如缩放和移位,这可能对线性方程有用),但我担心这会增加不必要的计算/设计变量/约束。

是否有更简单/更好的解决方法? (也许通过允许变量有多个名称?)最好的做法是让一个具有不同名称的变量等于先前的输出/输入?

一个简单的例子:

import openmdao.api as om
model = om.Group()
    model.add_subsystem('xcomp',subsys=om.IndepVarComp(name='x',val=np.zeros((3,2))),promotes_outputs=['*'])
model.connect('x','y')
p = om.Problem(model)
p.setup(force_alloc_complex=True)

p.set_val('x', np.array([[1.0 ,3],[10 ,-5],[0,3.1]])) 
p.run_model()

因错误而崩溃

NameError: <model> <class Group>: Attempted to connect from 'x' to 'y', but 'y' doesn't exist.

虽然这在使用以下 LinkVarComp 组件时有效(但我想添加新的变量和计算)

import openmdao.api as om 
import numpy as np
from math import prod

class LinkVarComp(om.ExplicitComponent):
    """
    Component containing
    """
    def initialize(self):
        """
        Declare component options.
        """
        self.options.declare('shape', types=(int,tuple),default=1)
        self.options.declare('scale', types=int,default=1)
        self.options.declare('shift', types=float,default=0.)
        self.options.declare('input_default', types=float,default=0.)
        self.options.declare('input_name', types=str,default='x')
        self.options.declare('output_name', types=str,default='y')
        self.options.declare('output_default', types=float,default=0.)
        self.options.declare('input_units', types=(str,None),default=None)
        self.options.declare('output_units', types=(str,None),default=None)

    def setup(self):
        self.add_input(name=self.options['input_name'],val=self.options['input_default'],shape=self.options['shape'],units=self.options['input_units'])
        self.add_output(name=self.options['output_name'],val=self.options['output_default'],shape=self.options['shape'],units=self.options['output_units'])
        if type(self.options['shape']) == int:
            n = self.options['shape']
        else:
            n =prod( self.options['shape'])
        ar = np.arange(n)
        self.declare_partials(of=self.options['output_name'] , wrt=self.options['input_name'], rows=ar, cols=ar,val=self.options['scale'])

    def compute(self, inputs, outputs):
        outputs[self.options['output_name']] = self.options['scale']*inputs[self.options['input_name']] + self.options['shift']

model = om.Group()
model.add_subsystem('xcomp',subsys=om.IndepVarComp(name='x',val=np.zeros((3,2))),promotes_outputs=['*'])
model.add_subsystem('link', LinkVarComp(shape=(3,2)),
                        promotes_inputs=['*'],
                        promotes_outputs=['*'])

p = om.Problem(model)
p.setup(force_alloc_complex=True)

p.set_val('x', np.array([[1.0 ,3],[10 ,-5],[0,3.1]]))
p.run_model()
print(p['y'])

输出预期:

[[ 1.   3. ]
 [10.  -5. ]
 [ 0.   3.1]]

【问题讨论】:

    标签: openmdao


    【解决方案1】:

    在 OpenMDAO 中,您不能让同一个变量具有两个不同的名称。那根本不允许。

    您提出的解决方案是有效地创建一个单独的组件来保存输出的副本。这样可行。您可以使用 ExecComp 来获得相同的效果,但代码更少:

    import numpy as np
    import openmdao.api as om
    
    model = om.Group()
    model.add_subsystem('xcomp',subsys=om.IndepVarComp(name='x',val=np.zeros((3,2))),promotes_outputs=['*'])
    model.add_subsystem('ycomp', om.ExecComp("y=x", shape=(3,2)), promotes=['*'])
    
    
    p = om.Problem(model)
    p.setup(force_alloc_complex=True)
    
    p.set_val('x', np.array([[1.0 ,3],[10 ,-5],[0,3.1]])) 
    p.run_model()
    
    print(p['x'])
    print(p['y'])
    

    一般来说,我自己可能实际上不会这样做。好像有点浪费相反,我会修改我的后处理脚本以查找y,如果没有找到,则改为获取x

    【讨论】:

    • 谢谢,我想知道我是否遗漏了什么,但后处理选项可能更有效。问题是当它在具有各种选项的子系统中变得复杂时,这需要设置额外的逻辑(if 语句等)来检查要使用的变量。我会使用 Execcomp,但我想知道是否会有性能损失(因为它以数字方式计算导数)。
    • 与衍生产品相关的 exec-comp 有一些小的性能损失。通常,您放入 exec-comp 的功能非常便宜,以至于没关系。如果你正在做这样的事情,它只是一个通过它可能值得为它制作一个组件只是为了节省成本(因为衍生物是如此简单。)
    猜你喜欢
    • 2017-02-04
    • 2016-04-04
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-19
    • 2020-11-19
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多