如何防止 OpenMDAO 组件为导数分配大型密集数组?
How can I prevent OpenMDAO components from allocating large dense arrays for derivatives?
我有一些 OpenMDAO 组件,它们对一维 x 坐标列表和一维 y 坐标列表进行数学运算,输出每对的距离和角度列表。每个计算仅依赖于一个 x 和 y。
它们类似于
x = cos(t)
y = sin(t)
d2 = x**2 + y**2
我在 setup
方法中配置的位置
self.add_input("t", shape_by_conn=True)
self.add_output("x", copy_shape="t")
self.add_output("y", copy_shape="t")
self.add_output("d2", copy_shape="t")
和 compute
方法按预期工作。通常 t
是来自 np.linspace()
.
的一维数组
在setup_partials
我有
size = self._get_var_meta("t", "size")
self.declare_partials("x", ["t"],
rows=range(size), cols=range(size))
self.declare_partials("y", ["t"],
rows=range(size), cols=range(size))
self.declare_partials("d2", ["t"],
rows=range(size), cols=range(size))
.
在 compute_partials
中,我将一维 numpy 数组传递给 J["x", "t"]
等等。当我将 t
设置为长度 10 时,测试 check_partials
不会抛出任何错误。如果我没有 out_stream=None
.
,我确实看到它在输出中打印 10x10 数组
然而,如果我将 t
设置为 100000,当我 运行
prob.check_partials(out_stream=None)
它试图分配一个大数组:Unable to allocate 74.5 GiB for an array with shape (100000, 100000) and data type float64
。我原以为只会分配大小为 ~100000 的数组,而不是 100000^2。
如果我不 运行 check_partials
而是附上 ExecComp
:
也会出现同样的错误
self.add_subsystem("hypotsq", om.ExecComp("d_sq = x**2 + y**2",
has_diag_partials=True,
x={"shape_by_conn":True},
y={"copy_shape": "x"},
d_sq={"copy_shape": "y"}))
doc page for Spartial partial derivatives 提到了“稀疏 AssembledJacobian
” 和“稀疏全局雅可比”。我可能需要其中之一吗?还有什么我遗漏的吗?
在正常运行期间,它只会分配稀疏雅可比矩阵。但是,在 check_partials 期间,OpenMDAO 为要放入的 FD 部分分配了第二个密集数组。
OpenMDAO 这样做是因为一般来说,获得正确的 rows/cols 是棘手的,而且它通常有助于查看完整的雅可比矩阵。它显然会导致您的代码出现问题,我可以建议一些解决方法:
当您 运行 check_partials 时,将您的组件设置为更小的尺寸。您可以在 运行 时使用全尺寸,但检查时尺寸过大。
如果检查 t
的大值对您很重要,那么请考虑使用 directional derivative checking instead.
我有一些 OpenMDAO 组件,它们对一维 x 坐标列表和一维 y 坐标列表进行数学运算,输出每对的距离和角度列表。每个计算仅依赖于一个 x 和 y。
它们类似于
x = cos(t)
y = sin(t)
d2 = x**2 + y**2
我在 setup
方法中配置的位置
self.add_input("t", shape_by_conn=True)
self.add_output("x", copy_shape="t")
self.add_output("y", copy_shape="t")
self.add_output("d2", copy_shape="t")
和 compute
方法按预期工作。通常 t
是来自 np.linspace()
.
在setup_partials
我有
size = self._get_var_meta("t", "size")
self.declare_partials("x", ["t"],
rows=range(size), cols=range(size))
self.declare_partials("y", ["t"],
rows=range(size), cols=range(size))
self.declare_partials("d2", ["t"],
rows=range(size), cols=range(size))
.
在 compute_partials
中,我将一维 numpy 数组传递给 J["x", "t"]
等等。当我将 t
设置为长度 10 时,测试 check_partials
不会抛出任何错误。如果我没有 out_stream=None
.
然而,如果我将 t
设置为 100000,当我 运行
prob.check_partials(out_stream=None)
它试图分配一个大数组:Unable to allocate 74.5 GiB for an array with shape (100000, 100000) and data type float64
。我原以为只会分配大小为 ~100000 的数组,而不是 100000^2。
如果我不 运行 check_partials
而是附上 ExecComp
:
self.add_subsystem("hypotsq", om.ExecComp("d_sq = x**2 + y**2",
has_diag_partials=True,
x={"shape_by_conn":True},
y={"copy_shape": "x"},
d_sq={"copy_shape": "y"}))
doc page for Spartial partial derivatives 提到了“稀疏 AssembledJacobian
” 和“稀疏全局雅可比”。我可能需要其中之一吗?还有什么我遗漏的吗?
在正常运行期间,它只会分配稀疏雅可比矩阵。但是,在 check_partials 期间,OpenMDAO 为要放入的 FD 部分分配了第二个密集数组。
OpenMDAO 这样做是因为一般来说,获得正确的 rows/cols 是棘手的,而且它通常有助于查看完整的雅可比矩阵。它显然会导致您的代码出现问题,我可以建议一些解决方法:
当您 运行 check_partials 时,将您的组件设置为更小的尺寸。您可以在 运行 时使用全尺寸,但检查时尺寸过大。
如果检查
t
的大值对您很重要,那么请考虑使用 directional derivative checking instead.