在 OpenMDAO 中,我可以使用 set_check_partial_options 来防止检查某些导数吗?

In OpenMDAO can I use set_check_partial_options to prevent certain derivatives from being checked?

我有一个om.ExplicitComponent,其中一些导数是精确的(解析的)并且可以用复杂的步骤方法检查(cs),一些导数是解析的但不能用 cs 检查,有些只能用有限差分求值。

import openmdao.api as om

from scipy.special import ellipe, ellipk
from scipy.special import hyp2f1

class MWE(om.ExplicitComponent):
    def setup(self):
        self.add_input("a")
        self.add_input("b")
        self.add_input("c")
        self.add_output("x")
        self.add_output("y")
        self.add_output("z")

    def compute(self, inputs, outputs):
        a = inputs["a"]
        b = inputs["b"]
        c = inputs["c"]
        outputs["x"] = a**2
        outputs["y"] = ellipe(b)
        outputs["z"] = hyp2f1(1 / 10, a, 1 / 2, c)

    def setup_partials(self):
        self.declare_partials("x", ["a"], method="exact")
        self.declare_partials("y", ["b"], method="exact")
        self.declare_partials("z", ["a"], method="fd")
        self.declare_partials("z", ["c"], method="exact")

    def compute_partials(self, inputs, J):
        a = inputs["a"]
        b = inputs["b"]
        c = inputs["c"]
        J["x", "a"] = 2 * a

        J["y", "b"] = (ellipe(b) - ellipk(b)) / (2 * b)

        J["z", "c"] = (a / 5) * hyp2f1(11 / 10, 1 + a, 3 / 2, c)

有没有一种方法可以使用一次或多次调用 set_check_partial_optionscheck_partials

您可以使用 set_check_partials 方法对如何执行检查进行细粒度控制。此方法在特定组件的 setupsetup_partials 内设置,可让您分别控制每个输入的设置。

如果要将整个组件设置为 CS 或 FD,可以使用“*”作为 wrt 参数。

请注意,这些组件级设置会被您传递给 check_partials 方法本身的 method 参数覆盖。所以只需将其留空并使用其自己的本地设置配置每个组件。

不幸的是,V3.15 中似乎有一个与 set_check_partials_options 有关的错误。以下是模型的正确语法,但如果您取消注释 cs 选项,则会引发错误。对于 V3.15 及更低版本,您必须使用 CS 或 none 检查所有内容。 V3.16应该会修复

import openmdao.api as om

from scipy.special import ellipe, ellipk
from scipy.special import hyp2f1

class MWE(om.ExplicitComponent):
    def setup(self):
        self.add_input("a")
        self.add_input("b")
        self.add_input("c")
        self.add_output("x")
        self.add_output("y")
        self.add_output("z")

    def compute(self, inputs, outputs):
        a = inputs["a"]
        b = inputs["b"]
        c = inputs["c"]
        outputs["x"] = a**2
        outputs["y"] = ellipe(b)
        outputs["z"] = hyp2f1(1 / 10, a, 1 / 2, c)

    def setup_partials(self):
        self.declare_partials("x", ["a"], method="exact")
        self.declare_partials("y", ["b"], method="exact")
        self.declare_partials("z", ["a"], method="fd")
        self.declare_partials("z", ["c"], method="exact")


        # self.set_check_partial_options(wrt="a", method="cs") # bug in V3.15
        self.set_check_partial_options(wrt="a", form="backward") 
        self.set_check_partial_options(wrt="b", form="central")

    def compute_partials(self, inputs, J):
        a = inputs["a"]
        b = inputs["b"]
        c = inputs["c"]
        J["x", "a"] = 2 * a

        J["y", "b"] = (ellipe(b) - ellipk(b)) / (2 * b)

        J["z", "c"] = (a / 5) * hyp2f1(11 / 10, 1 + a, 3 / 2, c)



if __name__ == "__main__":

    p = om.Problem()
    p.model = MWE()

    p.setup(force_alloc_complex=True)

    # set some workable initial values to avoid inf
    p['a'] = 2. 
    p['b'] = -2. 
    p['c'] = -2. 

    p.run_model()
    p.model.list_outputs()

    p.check_partials()