Создайте большую разреженную матрицу из нескольких меньших разреженных матриц

Я использую библиотеку Eigen для решения задачи FEM, в которой я использую несколько подобных разреженных матриц для различных видов производных, которые я вычисляю. Чтобы построить разреженную матрицу для решения системы, я хотел бы использовать инициализатор запятой, но он не поддерживается для разреженных матриц (https://eigen.tuxfamily.org/dox/group__TutorialSparse.html и https://stackoverflow.com/a/43532618/15811117). В этом ответе Анри Менке предлагает неподдерживаемый продукт Кронекера Eigen, хотя я не думаю, что это сработает здесь.

С сеткой NxM я вычисляю несколько производных матриц (которые являются разреженными), Dx2, Dxz, и Dz2 размером N*M x N*M. Моя матрица решателя выглядит следующим образом (K - это просто константы, а 0 - это просто заполнитель - нулевая матрица, N * M x N * M)

K3*Dx2 + K1*Dz2   K2*Dxz            0              0                 0
K2*Dxz            K3*Dz2 + K1*Dx2   0              0                 0
0                 0                 K1*(Dx2+Dz2)   0                 0
0                 0                 0              K3*Dx2 + K1*Dz2   K2*Dxz
0                 0                 0              K2*Dxz            K3*Dz2 + K1*Dx2

На данный момент я создаю его, преобразовывая разреженный в плотный, используя инициализатор запятой, а затем преобразовывая обратно в разреженный с помощью .sparseView(). Единственная проблема заключается в том, что если сетка намного больше 16x16, я получаю ошибку std::bad_alloc (что вполне ожидаемо, поскольку создается огромная матрица: 5*N*M x 5*N*M), и мне нужна сетка не менее 100x100 (и не всегда будет столько 0 матриц, сколько показано сейчас, хотя она останется разреженной матрицей).

Каков наилучший способ построить эту матрицу? Я подумал о том, чтобы попытаться использовать триплеты для этого, подобно этому (Преобразовать собственную матрицу в триплетную форму C++).

Редактировать: я не думаю, что использовать триплеты будет так просто (хотя я сейчас пытаюсь это сделать), потому что я редактирую несколько значений в каждой матрице D_ _ для граничных условий... если нет способ найти триплет в std::vector с заданным номером строки и столбца?

Обновление: оба метода произведения Триплет и Кронекер возможны, но я столкнулся с несколькими проблемами:

С продуктом Кронекера я получаю следующую ошибку (около сотни раз) при компиляции:

.../eigen/unsupported/Eigen/src/KroneckerProduct/KroneckerTensorProduct.h:225:97: error: no type named ‘ReturnType’ in ‘struct Eigen::ScalarBinaryOpTraits<int, std::complex<double>, Eigen::internal::scalar_product_op<int, std::complex<double> > >’

С помощью метода Triplet я определил несколько операторов и функцию для «сдвига» матрицы в нужное место (в основном то, что делает произведение Кронекера). Мне просто нужно выяснить проблему выхода индекса за пределы.


person Izek H    schedule 12.07.2021    source источник
comment
Являются ли производные матрицы разреженными?   -  person CJR    schedule 13.07.2021
comment
@CJR да, их мало; изначально они были созданы с помощью функции setFromTriplets. Сейчас я пытаюсь понять, смогу ли я сохранить их как векторы троек, пока не построю эту матрицу.   -  person Izek H    schedule 13.07.2021
comment
Почему вы считаете, что продукт Кронекера не является жизнеспособным решением? С продуктом Кронекера вы можете создать полученные матрицы, повторяющие Dx2, Dxz и Dz2, а затем суммировать их для получения окончательной матрицы.   -  person LGrementieri    schedule 13.07.2021
comment
@LGrementieri Думаю, я неправильно понял, как использовать продукт Кронекера - я согласен, он должен работать. К сожалению, при компиляции я получаю сотни ошибок :( См. update.   -  person Izek H    schedule 14.07.2021


Ответы (1)


Проблема возникает из-за того, что матрицы, которые я использовал в продукте Кронекера, были типа SparseMatrix<int> и SparseMatrix<complex<double>>. Для int и complex<double> нет перегрузок операторов, поэтому, создавая обе матрицы совместимых типов, код компилируется и выполняется, как и ожидалось.

person Izek H    schedule 15.07.2021