Как можно использовать OpenMDAO для решения линейной системы уравнений без инвертирования матрицы A?

У меня есть система уравнений в виде:

Ax = b

Где A и b — это смесь известных состояний и скоростей состояний, полученных из более ранних компонентов, а x — вектор четырех еще неизвестных скоростей состояний. Я использовал Matlab для линеаризации задачи, все, что мне нужно сделать сейчас, это создать некоторые компоненты, чтобы найти x. Однако обратная величина A велика с точки зрения количества переменных в каждом индексе, поэтому я не могу просто превратить их в простое линейное уравнение. Может кто подскажет маршрут?


person Rory McDonald    schedule 11.02.2021    source источник


Ответы (1)


Я не совсем понимаю, что вы имеете в виду, говоря, что инверсия A велика с точки зрения количества переменных в каждом индексе, однако я думаю, что инверсия A слишком велика и плотна для вычисления и хранения в памяти.

OpenMDAO или нет, когда вы сталкиваетесь с этой ситуацией, вы вынуждены использовать итеративный линейный решатель, такой как gmres. Так что в целом такой подход необходим и здесь.

В OpenMDAO есть LinearSystemComponent, который вы можете использовать как грубый план здесь. Однако он вычисляет факторизацию и сохраняет ее, а это не то, что вам нужно. Тем не менее, он дает вам представление о том, как представить линейную систему в виде неявный компонент в OpenMDAO.

В общем, вам нужно подумать об определении линейного остатка: R = Ax-b = 0

Ваш компонент будет иметь два входа A и b и один выход x.

Два ключевых метода здесь — apply_nonlinear и solve_nonlinear. Я понимаю, что слово nonlinear в именах методов сбивает с толку. OpenMDAO предполагает, что анализ нелинейный. В вашем случае это происходит линейно, но вы все равно используете методы nonlinear.

Я предполагаю, что, хотя вы не можете вычислить/сохранить [A] в обратном порядке, вы можете вычислить/сохранить A (возможно, в разреженном формате). В этом случае вы можете передать массив разреженных данных [A] в качестве входных данных и заполнить разреженную матрицу по мере необходимости.

метод apply_nonlinear будет выглядеть так:

def apply_nonlinear(self, inputs, outputs, residuals):
        """
        R = Ax - b.
        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        residuals : Vector
            unscaled, dimensional residuals written to via residuals[key]
        """
        
        residuals['x'] = inputs['A'].dot(outputs['x']) - inputs['b']

Ключ к вашему вопросу действительно solve_nonlinear method. Это будет выглядеть примерно так: (используя scipy gmres ):

def solve_nonlinear(self, inputs, outputs):
        """
        Use numpy to solve Ax=b for x.
        Parameters
        ----------
        inputs : Vector
            unscaled, dimensional input variables read via inputs[key]
        outputs : Vector
            unscaled, dimensional output variables read via outputs[key]
        """
    
        
        x, exitCode = gmres(inputs['A'], inputs['b'])

        outputs['x'] = x
person Justin Gray    schedule 12.02.2021
comment
Да, это то, что я имел в виду под слишком большим. Ах, хорошо, я думаю, что я не за горами, прежде чем я начал искать решение, у меня был неявный компонент с остатком ['outputA'] = уравнение ... и я переставил уравнение равным 0. Я не мог выясните, как использовать решатель Newton только для этого компонента. Это неявный компонент: github.com/RoryMcDonald/Ebike- LTS/blob/test/implicitSubstep/ . И именно здесь я ранее пытался использовать решатель newton, я думаю, что он решал все системы: github.com/RoryMcDonald/Ebike-LTS/blob/test/combineODE.py, строка 44. - person Rory McDonald; 12.02.2021
comment
Похоже ли, что моя первая попытка должна работать эквивалентно подходу LinearSystemComponent, и если да, то как мне настроить решатель Newton только для решения неявного компонента? - person Rory McDonald; 12.02.2021
comment
для линейной системы вам не нужен решатель Ньютона. Это нелинейный решатель. Здесь вам нужно будет реализовать метод solve_nonlinear самостоятельно, как в моем примере выше. Стандартные решатели OpenMDAO в этом случае использовать нельзя. - person Justin Gray; 12.02.2021