Почему компоненты выполняются два раза для каждой итерации Гаусса-Зейделя? (OpenMDAO 2.4.0)

1

Я использовал NonLinearBlockGS как nonlinear_solver для моей MDO-системы, состоящей из ExplicitComponents и это работает, как ожидалось. Сначала я использовал это с помощью простых математических функций (отсюда время выполнения << 1 с), но теперь я также внедряю систему с несколькими явными компонентами с временем работы около одной минуты или более. Это, когда я заметил, что NonLinearBlockGS фактически необходимо запустить инструменты в связанной системе два раза за итерацию. Эти прогоны исходят из self._iter_execute() и self._run_apply() в _run_iterator() решателя (класс Solver в файле solver.py).

Мой главный вопрос: нужны ли два прогона на итерацию, и если да, то почему?

Кажется, что первый запуск компонента (self.iter_execute()) использует начальное предположение для переменных обратной связи, которые необходимо self.iter_execute() а затем последовательно запускает компоненты при обновлении любых данных, связанных с форвардом. Это тот шаг, который я ожидал бы от Гаусса-Зейделя. Но затем второй запуск компонента (self._run_apply()) снова запускает компоненты с обновленными переменными обратной связи, которые возникли в результате первого запуска, сохраняя при этом форварды как они были в этом первом запуске. Если я не ошибаюсь, эта информация тогда (только) используется для оценки сходимости этой итерации (self._iter_get_norm()).

Вместо того, чтобы выполнить этот второй запуск внутри итерации, не было бы более эффективным прямое продолжение следующей итерации? В этой итерации мы можем использовать новые значения переменных обратной связи и делать еще один self._iter_execute() с обновлением данных, связанных с форвардом, и затем оценивать конвергенцию на основе разницы между результатами между этими двумя итерациями. Конечно, это означает, что для оценки конвергенции нам нужны как минимум две итерации, но она сохраняет один компонент за одну итерацию. (Это фактически существующая реализация, которая у меня есть для конвергенции этих компонентов в MATLAB и работает, как ожидалось, следовательно, она находит тот же конвергентный дизайн, но с половиной объема выполнения компонентов).

Итак, еще один способ поставить это: зачем нам нужно self._run_apply() на каждой итерации при сближении Гаусса-Сейделя? (И можно ли это отключить?)

Теги:
openmdao

1 ответ

1
Лучший ответ

На ваш вопрос есть несколько разных аспектов. Во-первых, я расскажу о деталях solve_nonlinear vs apply_nonlinear. С помощью лежащих в основе математических алгоритмов OpenMDAO, основанных на структуре MAUD, solve_nonlinear вычисляет только значения выходных значений (не устанавливает остаточные значения). apply_nonlinear вычисляет только остатки (и не устанавливает выходы). Для подклассов ExplicitComponent пользователь только реализует метод compute, а базовый класс реализует как solve_nonlinear и apply_nonlinear с использованием compute.

Как вы описали его, в OpenMDAO V2.4 текущая реализация NonlinearBlockGaussSeidel для каждой итерации выполняет один рекурсивный solve_nonlinear вызов в своей группе, а затем вызывает apply_nonlinear для проверки остатка и поиска конвергенции.

Тем не менее, вы также правы, что мы могли бы сделать это более эффективно. Модификация, которую вы предложили алгоритму, будет работать, и мы поместим ее в конвейер разработки для V2.6 (со времени этого сообщения мы как раз собираемся выпустить V2.5, и не будет время, чтобы добавить это в этот выпуск)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню