Как эффективно собрать матрицу жесткости несколько раз, используя Cython - PullRequest
0 голосов
/ 22 декабря 2018

Я пишу свой собственный решатель конечных элементов для динамического моделирования в cython с использованием библиотеки ceygen (представление в виде векторов и матриц Эйгена в оболочке памяти).На каждом временном шаге я должен собрать матрицу жесткости и оценить ее наибольшее собственное значение с помощью теоремы о круге Гершгоринга, добавив абсолютную величину каждой записи строки в матрице.Для сборки я использую формат coo_matrix.Вот краткая версия моего ассемблерного кода:

for el in range(nElemens):

    Klocal()

    for i in range(9):
        for j in range(9):
            data(index) = Klocal(i,j)
            index += 1

K = coo_matrix((data, (row, col)), shape=(ndof, ndof)).tocsc()
K.eliminate_zeros()

При запуске профилировщика я получаю следующие результаты:

 ncalls  tottime  percall  cumtime  percall  filename:lineno(function)
  458    264.720  0.578    264.720  0.578    {built-in method lexsort}
    1    84.764   84.764   486.663  486.663  main.py:9(main)
  458    61.473   0.134    343.218  0.749    coo.py:460(_sum_duplicates)
  458    12.933   0.028    12.933   0.028    {method 'reduceat' of 'numpy.ufunc' objects}
 2775    11.192   0.004    11.193   0.004    {method 'reduce' of 'numpy.ufunc' objects}
16063    8.627    0.001    8.627    0.001    {built-in method array}
28419916 6.933    0.000    6.933    0.000    membrane3D.pyx:366(membrane3DKmat)

Огромное количество времени теряется lexsortи reduceat функции, вызываемые изнутри scipy каждый раз, когда я собираю матрицу.Мой вопрос заключается в том, могу ли я повторно использовать ненулевую структуру матрицы (которая остается постоянной и может быть легко вычислена) в scipy, чтобы сэкономить время?Или, в качестве альтернативы, вы бы порекомендовали мне использовать обертку для разреженной матрицы Эйгена?

Любая помощь будет признательна!

...