Я расширил свой сценарий OpenMDAO, включив в него подитерацию. По сути, у меня есть гребной винт, распределение хорды и крутки которого определяется условиями крейсерского полета (с коллективным углом), где моей целью является эффективность (с рядом ограничений). Некоторое время это работало чудесно. Подитерация включает в себя оптимизацию условия зависания, где моя проектная переменная является только коллективной и RPM (отличной от крейсерской), но форма больше не является проектной переменной. Целевая функция переключается с эффективности на добротность. Я проверил все свои детали, и все настолько идеально, насколько я мог ожидать. Я проверил итоговые значения, и они также имеют смысл (подитерация при наведении проста, и я проверил цифры вручную). Вывод Compute_totals следующий:
Compute Totals:
{('volume_constraint_comp.figure_of_merit_hvr', 'omega_hvr'): array([[0.00020326]]),
('volume_constraint_comp.figure_of_merit_hvr', 'collective_hvr'):array([[-0.08223257]])}
Эти числа имеют смысл по сравнению с рассчитанными вручную полными производными от частичных величин.
Я сравнил это с check_totals и...
Full Model: 'figure_of_merit_hvr' wrt 'collective_hvr'
Forward Magnitude: 0.000000e+00
Fd Magnitude: 8.224099e-02 (fd:forward)
Absolute Error (Jfor - Jfd) : 8.224099e-02 *
Relative Error (Jfor - Jfd) / Jfd : 1.000000e+00 *
Raw Forward Derivative (Jfor)
[[-0.]]
Raw FD Derivative (Jfd)
[[-0.08224099]]
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Full Model: 'figure_of_merit_hvr' wrt 'omega_hvr'
Forward Magnitude: 0.000000e+00
Fd Magnitude: 2.032554e-04 (fd:forward)
Absolute Error (Jfor - Jfd) : 2.032554e-04 *
Relative Error (Jfor - Jfd) / Jfd : 1.000000e+00 *
Raw Forward Derivative (Jfor)
[[-0.]]
Raw FD Derivative (Jfd)
[[0.00020326]]
«Прямая величина» равна 0, хотя это должно быть значение, указанное в Compute_totals. Что могло бы стать причиной этого? Я проверил способ созданияfig_of_merit_hvr:
prob.model.add_subsystem(
"volume_constraint_comp",
comp,
promotes_inputs=[
"Rtip",
"radii",
"chord",
"disk_area",
"CT_ff",
"CT_hvr",
"CP_hvr",
"theta_cp",
"omega_hvr",
"collective_hvr",
"speedofsound"],
promotes_outputs=[
"volume",
"blade_area",
"solidity",
"ct_over_sigma_ff",
"ct_over_sigma_hvr",
"theta_at_75",
"figure_of_merit_hvr",
"mach_tip_hvr"])
Я также подтвердил, что мой N2 верен.
Очевидно, я как-то не правильно подключаю фигуру_of_merit_hvr. Есть какие-нибудь советы о чем-то еще, что я мог бы проверить?
Я попробовал несколько разных способов убедиться, что мои производные верны и цель поставлена правильно. Однако с настройкой явно что-то не так. Я распечатал подробности дела:
print("Design Variables:")
for name, options in _no_acoustic_constraint_hvr.model.get_design_vars().items():
print(f" {name}: {options}")
print("\nObjectives:")
for name, options in _no_acoustic_constraint_hvr.model.get_objectives().items():
print(f" {name}: {options}")
print("\nCompute Totals:")
totals = p_no_acoustic_constraint_hvr.compute_totals(
of=['volume_constraint_comp.figure_of_merit_hvr'])
print(totals)
p_no_acoustic_constraint_hvr.check_totals()
И вроде все настроено правильно. Я также просмотрел N2, вручную рассчитал производные и затем подтвердил то, что вычислено.
Я также просмотрел похожие проблемы, которые указывали на то, что я уже искал, и подтвердил, что предложения не указывают на решение.
Напомним: коллектив & RPM -> Ct & Cp -> FM. Коллектив и частота вращения являются расчетными переменными; ФМ объективен.


В этом случае я обменялся дополнительной информацией в автономном режиме и разработал решение, но я резюмирую ее здесь для других, кому это может быть интересно:
Диаграмма N2, показанная пользователем, указывает на отсутствие производных для нескольких компонентов... обратите внимание на отсутствие черных квадратов в верхних правых квадрантах компонентов, которые обычно указывают на зависимость выходных данных от входных.
В данном случае Лен определил эти производные, используя API «Matrix-Free» в OpenMDAO. То есть они определяются с использованием compute_jacvec_product вместо compute_partials. Более того, Лен создал этот метод с расчетом на то, что OpenMDAO сможет запускать эту задачу только в обратном режиме. В прямом режиме эти частные производные внутри компонента не вычисляются.
def compute_jacvec_product(self, inputs, d_inputs, d_outputs, mode):
# There is no forward differencing method for this.
if mode == 'fwd':
# No doutputs were provided here
pass
# We are going to only run in reverse (or backwards) mode.
elif mode == 'rev':
# All dinputs were computed here.
Решение относительно простое. Пользователь может заставить OpenMDAO вычислять производные в обратном режиме, используя
problem.setup(..., mode='rev')
Благодаря этому изменению производные в методах compute_jacvec_product вычисляются правильно, а итоговые суммы являются правильными.
Я попытался использовать два промежуточных значения в качестве целей (Ct и Cp). Они работают нормально, так что это что-то вроде того, как я перехожу от Ct и Cp к FM.