Пример записи/доступа к производным в эта ссылка у меня отлично работает, если я просто скопирую и вставлю код. Я пытаюсь выяснить, почему подобный метод не работает для моей собственной проблемы. Я установил параметры записи идентичными. Я попытался перечислить некоторые различия, но не уверен, что они могут быть причиной этого:
Я не уверен, какое еще понимание я могу дать. Может быть очевидная вещь, которую я упускаю. Любая идея?
Вот диаграммы N ^ 2 моей проблемы и примера проблемы.
Вот фрагмент кода.
prob = Problem()
probname = prob.model = Group()
recordername='recorder.sql'
GLOBAL_DESIGN_VAR = IndepVarComp()
#"The design variables Indepvar - Promotes none of the variables"
probname.add_subsystem('GLOBAL_DESIGN_VAR', GLOBAL_DESIGN_VAR)
listofloadcases=[inp.fatiguename]
AERO_GroupName='AERO%s' %''.join(listofloadcases)
probname.add_subsystem(AERO_GroupName, AERO(loadcase=listofloadcases))
for key,val in infodict['sysdes']['desvar'].items():
GLOBAL_DESIGN_VAR.add_output(key, val['init'])
probname.add_design_var('GLOBAL_DESIGN_VAR.{}'.format(key),lower=val['min'], upper=val['max'])
probname.connect('GLOBAL_DESIGN_VAR.{}'.format(key), '{}.{}'.format(AERO_GroupName,key))
probname.add_objective('{}.cumPSDerror'.format(AERO_GroupName))
probname.add_constraint('{}.cumDELerror'.format(AERO_GroupName),upper=0.1)
prob.driver=ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['disp'] = True
prob.driver.options['tol'] = 1e-9
recorder = SqliteRecorder(recordername)
prob.driver.add_recorder(recorder)
prob.driver.recording_options['includes'] = []
prob.driver.recording_options['record_inputs'] = True
# prob.driver.recording_options['record_outputs'] = True
prob.driver.recording_options['record_objectives'] = True
prob.driver.recording_options['record_constraints'] = True
prob.driver.recording_options['record_desvars'] = True
prob.driver.recording_options['record_derivatives'] = True
prob.setup(check=True)
prob.run_driver()
prob.cleanup()
cr = CaseReader('recorder.sql')
# Get derivatives associated with the last iteration.
derivs = cr.get_case(0).jacobian
# check that derivatives have been recorded.
print(set(derivs.keys()))
это то, что я получаю, когда я запускаю это
case = cr.get_case(-1)
print(case)
print(case.jacobian.keys())
поэтому print(case) работает, но jacobian пуст
driver rank0:SLSQP|20 {'GLOBAL_DESIGN_VAR.d2100': array([1.29472574]), 'GLOBAL_DESIGN_VAR.Factor_c': array([1.29491178]), 'GLOBAL_DESIGN_VAR.lus': array([1.28847898]),
'GLOBAL_DESIGN_VAR.ng': array([1.29981202]), 'GLOBAL_DESIGN_VAR.bl': array([1.2948257]), 'GLOBAL_DESIGN_VAR.d1700': array([1.29472449]),
'GLOBAL_DESIGN_VAR.sFactor_c': array([1.29981202]), 'GoldflexFLS12.error': array([3.04801276]), 'GoldflexFLS12.Lerror': array([0.73301603])}
Traceback (most recent call last):
File "<ipython-input-6-9a0bfa8ec35f>", line 5, in <module>
print(case.jacobian.keys())
AttributeError: 'NoneType' object has no attribute 'keys'
НОВЫЙ КОД, который можно запустить;
from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, SqliteRecorder, CaseReader
from openmdao.api import Group
from openmdao.api import ExplicitComponent
class Exp(ExplicitComponent):
def setup(self):
self.add_input('des1',val=1)
self.add_input('des2',val=1)
self.add_output('out',val=1)
self.add_output('con',val=1)
self.declare_partials('*', '*',method='fd',step=0.001)
def compute(self, inputs, outputs):
outputs['out']=inputs['des1']**2+inputs['des2']
outputs['con']=inputs['des1']
class AERO(Group):
def setup(self):
self.add_subsystem('Exp',Exp(),promotes=['*'])
infodict = {'desvar':{'des1':{"fdstep": 0.1,"init": 1.0,"max": 1.3,"min": 0.8},'des2':{"fdstep": 0.1,"init": 2.0,"max": 1.3,"min": 0.8}}}
prob = Problem()
probname = prob.model = Group()
recordername='recorder.sql'
GLOBAL_DESIGN_VAR = IndepVarComp()
probname.add_subsystem('GLOBAL_DESIGN_VAR', GLOBAL_DESIGN_VAR,promotes=['*'])
probname.add_subsystem('AERO', AERO(),promotes=['*'])
for key,val in infodict['desvar'].items():
GLOBAL_DESIGN_VAR.add_output(key, val['init'])
probname.add_design_var(key,lower=val['min'], upper=val['max'])
probname.add_objective('out')
probname.add_constraint('con',upper=0.1)
prob.driver=ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
prob.driver.options['disp'] = True
prob.driver.options['tol'] = 1e-9
recorder = SqliteRecorder(recordername)
prob.driver.add_recorder(recorder)
prob.driver.recording_options['includes'] = []
prob.driver.recording_options['record_inputs'] = True
# prob.driver.recording_options['record_outputs'] = True
prob.driver.recording_options['record_objectives'] = True
prob.driver.recording_options['record_constraints'] = True
prob.driver.recording_options['record_desvars'] = True
prob.driver.recording_options['record_derivatives'] = True
prob.setup(check=True)
prob.run_driver()
prob.cleanup()
cr = CaseReader(recordername)
# Get derivatives associated with the last iteration.
derivs = cr.get_case(0).jacobian
# check that derivatives have been recorded.
print(set(derivs.keys()))
@JustinGray Это проблема с одним компонентом, как показано выше N2, кроме IndepVarComp. И это решатель LinearRunOnce по умолчанию (я предполагаю). Я прикрепляю рекордер к issue.driver.add_recorder(etc), поэтому я думаю, что это должно давать общие производные за итерацию. Я ошибаюсь?
@JustinGray Я добавил новый код, который вы можете запустить, в конце вопроса. Надеюсь, вы получите уведомление об этом комментарии. Единственная разница, которую я вижу, заключается в том, что явный компонент, находящийся внутри «группы», должен вызывать проблему. но не могли бы вы объяснить, почему и как это исправить?
Предполагая, что вы используете драйвер по умолчанию (RunOnceDriver) и вызываете run_driver(), причина, по которой вы не видите никаких производных, заключается в том, что драйвер по умолчанию никогда не запрашивает их, поэтому они никогда не вычисляются.
Итак, вам нужно выбрать драйвер на основе градиента, а затем обязательно установить
prob.driver.recording_options['record_derivatives'] = True
Вот минимальный рабочий пример:
from openmdao.api import Problem, ScipyOptimizeDriver, ExecComp, IndepVarComp, SqliteRecorder, CaseReader
# build the model
prob = Problem()
indeps = prob.model.add_subsystem('indeps', IndepVarComp())
indeps.add_output('x', 3.0)
indeps.add_output('y', -4.0)
prob.model.add_subsystem('paraboloid', ExecComp('f = (x-3)**2 + x*y + (y+4)**2 - 3'))
prob.model.connect('indeps.x', 'paraboloid.x')
prob.model.connect('indeps.y', 'paraboloid.y')
prob.driver = ScipyOptimizeDriver()
prob.driver.options['optimizer'] = 'SLSQP'
recorder = SqliteRecorder("cases.sql")
prob.driver.add_recorder(recorder)
prob.driver.recording_options['record_derivatives'] = True
prob.model.add_design_var('indeps.x', lower=-50, upper=50)
prob.model.add_design_var('indeps.y', lower=-50, upper=50)
prob.model.add_objective('paraboloid.f')
prob.setup()
prob.run_driver()
# minimum value
print(prob['paraboloid.f'])
# location of the minimum
print(prob['indeps.x'])
print(prob['indeps.y'])
prob.cleanup()
cr = CaseReader("cases.sql")
# driver_cases = cr.list_cases('driver')
# Get derivatives associated with the last iteration.
case = cr.get_case(-1)
print(case)
# check that derivatives have been recorded.
print(case.jacobian.keys())
Я мог ввести вас в заблуждение формулировкой «Драйвер LinearRunOnce». Наверное, я имел в виду решатель LinearRunOnce. Как написано в мануале это по умолчанию и я его не меняю. Но драйвер ScipyOptimizer с SLSQ. Я думал, что есть еще линейная система, которую нужно решить для полных производных. Пожалуйста, смотрите обновленный вопрос с минимальным кодом. Я все еще не могу получить вывод производных.
во-первых, если вы запустите предоставленный файл, который я дал в своем ответе, даст ли он вам производные? Я вижу их на своей машине, так что если нет... у вас, вероятно, просто не установлена последняя версия openmdao. Недавно мы выпустили версию 2.6. Попробуйте обновиться до этого. Во-вторых, пример, который вы привели, не проходит. Он нуждается в импорте и зависит от некоторой переменной, которая не определена: listofloadcases=[inp.fatiguename]
Я получаю производные как из вашего примера, так и из примера в руководстве. Но почему-то я не могу получить доступ к моему примеру кода. И да, фрагмент кода, который я вставил в свой вопрос, не запускается, поскольку группа, добавленная к проблеме, содержит явный компонент, который вызывает «внешний код Python», который является конфиденциальным. Я поместил туда код, чтобы проверить, не совершал ли я очевидную ошибку при добавлении модели, рекордера и т. д. В моем вопросе также есть диаграмма N2 этой проблемы. Я не могу отличить способ, которым я добавляю регистратор к проблеме, по сравнению с вашим.
Но когда я запускаю последнюю часть, я добавляю то, что получаю, в конец своего вопроса.
Я не могу предоставить больше рекомендаций без примера, который я могу проверить. Если вы можете изменить свой пример с помощью игрушечного компонента вместо внешнего, тогда я могу взглянуть еще раз.
Нам действительно нужен пример кода для работы. Я не вижу никаких звонков
list_inputs
в предоставленной ссылке. Я предполагаю, что вы подключаете записывающее устройство к системе, возможно, к системе верхнего уровня, а затем звонитеrun_model
. если у вас есть решатель NonlinearBlockGaussSeidel, которому не нужны производные, тогда не будет записано, и вы не сможете получить к ним доступ.