214class LUFactorisationAlgo
218 typedef MatrixT MatrixType;
219 typedef VectorT VectorType;
220 typedef typename MatrixType::ProfileType ProfileType ;
221 typedef typename MatrixType::ValueType ValueType;
222 typedef typename MatrixType::TagType TagType ;
225 LUFactorisationAlgo()
228 virtual ~LUFactorisationAlgo()
231 template <
typename AlgebraT>
232 void baseInit(AlgebraT& algebra, MatrixT
const& matrix)
234 m_is_parallel = matrix.isParallel();
235 m_alloc_size = matrix.getAllocSize();
236 if constexpr (
requires{matrix.blockSize();})
237 m_block_size = matrix.blockSize();
240 m_distribution = matrix.distribution();
241 m_lu_matrix.reset(matrix.cloneTo(
nullptr));
242 m_profile = &m_lu_matrix->getProfile();
243 m_work.resize(m_alloc_size);
244 m_work.assign(m_work.size(), -1);
245 algebra.allocate(AlgebraT::resource(matrix), m_x);
248 template <
typename AlgebraT>
249 void init(AlgebraT& algebra, MatrixT
const& matrix)
251 baseInit(algebra, matrix);
253 factorize(*m_lu_matrix);
255 blockFactorize(*m_lu_matrix);
260 void factorize(MatrixT& matrix,
bool bjacobi =
true)
278 auto nrows = modifier.nrows() ;
279 auto kcol = modifier.kcol() ;
280 auto dcol = modifier.dcol() ;
281 auto cols = modifier.cols() ;
282 auto values = modifier.data() ;
285 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
287 for (std::size_t irow = 1; irow < nrows; ++irow)
289 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
292 ValueType aik = values[k] / values[dcol[krow]];
294 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
296 for (
int j = k + 1; j < kcol[krow] + local_row_size[irow]; ++j)
299 int kj = m_work[jcol];
301 values[j] -= aik * values[kj];
304 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
305 m_work[cols[l]] = -1;
311 op.recvLowerNeighbLUData(values);
312 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
313 for (std::size_t irow = 1; irow < nrows; ++irow)
315 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
318 ValueType aik = values[k] / values[dcol[krow]];
320 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
322 for (
int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j)
325 int kj = m_work[jcol];
327 values[j] -= aik * values[kj];
330 for (
int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j)
333 int kj = m_work[jcol];
334 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
335 values[j] -= aik * values[kj];
338 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
339 m_work[cols[l]] = -1;
342 op.sendUpperNeighbLUData(values);
346 for (std::size_t irow = 1; irow < nrows; ++irow)
348 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
351 ValueType aik = values[k] / values[dcol[krow]];
353 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
355 for (
int j = k + 1; j < kcol[irow + 1]; ++j)
358 int kj = m_work[jcol];
360 values[j] -= aik * values[kj];
363 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
364 m_work[cols[l]] = -1;
370 void solveL(ValueType
const* y, ValueType* x)
const
374 auto nrows = view.nrows() ;
375 auto kcol = view.kcol() ;
376 auto dcol = view.dcol() ;
377 auto cols = view.cols() ;
378 auto values = view.data() ;
381 for (std::size_t irow = 0; irow < nrows; ++irow) {
382 ValueType val = y[irow];
383 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
384 val -= values[k] * x[cols[k]];
389 void solveU(ValueType
const* y, ValueType* x)
const
393 auto nrows = view.nrows() ;
394 auto kcol = view.kcol() ;
395 auto dcol = view.dcol() ;
396 auto cols = view.cols() ;
397 auto values = view.data() ;
400 auto& local_row_size = m_lu_matrix->getDistStructInfo().m_local_row_size;
401 for (
int irow = (
int)nrows - 1; irow > -1; --irow) {
403 ValueType val = y[irow];
404 for (
int k = dk + 1; k < kcol[irow] + local_row_size[irow]; ++k) {
405 val -= values[k] * x[cols[k]];
407 x[irow] = val / values[dk];
411 for (
int irow = (
int)nrows - 1; irow > -1; --irow) {
413 ValueType val = y[irow];
414 for (
int k = dk + 1; k < kcol[irow + 1]; ++k) {
415 val -= values[k] * x[cols[k]];
417 x[irow] = val / values[dk];
422#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
423 inline auto inv(Eigen::Map<Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor>>
const & block)
const
425 assert(block.determinant()!=0) ;
426 return block.inverse() ;
430 void blockFactorize(MatrixT& matrix,
bool bjacobi =
true)
446#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
447 using namespace Eigen;
448 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
449 using Block2DView = Eigen::Map<Block2D> ;
451 int N = m_block_size;
458 auto nrows = modifier.nrows() ;
459 auto kcol = modifier.kcol() ;
460 auto dcol = modifier.dcol() ;
461 auto cols = modifier.cols() ;
462 auto values = modifier.data() ;
471 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
474 for (std::size_t irow = 1; irow < nrows; ++irow)
479 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
488 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
489 Block2DView(values+k*N2,N,N) = aik ;
496 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
498 for (
int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j)
501 int kj = m_work[jcol];
504 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
513 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
514 m_work[cols[l]] = -1;
520 op.recvLowerNeighbLUData(values);
521 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
522 for (std::size_t irow = 1; irow < nrows; ++irow)
524 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
529 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
530 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
532 for (
int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j)
535 int kj = m_work[jcol];
538 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
541 for (
int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j)
544 int kj = m_work[jcol];
545 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
547 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
550 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
551 m_work[cols[l]] = -1;
554 op.sendUpperNeighbLUData(values);
559 m_inv_diag_matrix.reserve(nrows);
560 for (std::size_t irow = 0; irow < nrows; ++irow)
562 m_inv_diag_matrix.emplace_back(Block2DView(values+dcol[irow]*N2,N,N)) ;
567 for (std::size_t irow = 1; irow < nrows; ++irow)
572 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
581 aik = Block2DView(values+k*N2,N,N) * inv(Block2DView(values+dcol[krow]*N2,N,N)) ;
582 Block2DView(values+k*N2,N,N) = aik ;
590 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
592 for (
int j = k + 1; j < kcol[irow + 1]; ++j)
595 int kj = m_work[jcol];
598 Block2DView(values+j*N2,N,N) -= aik * Block2DView(values+kj*N2,N,N) ;
607 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
608 m_work[cols[l]] = -1;
614 m_inv_diag_matrix.reserve(nrows);
615 for (std::size_t irow = 0; irow < nrows; ++irow)
617 m_inv_diag_matrix.emplace_back(Block2DView(values+dcol[irow]*N2,N,N)) ;
622 throw Arccore::FatalErrorException(
623 A_FUNCINFO,
"Eigen is required for BlockILU factorization");
626#if defined(EIGEN3_DISABLED)
631 int N = m_block_size;
638 auto nrows = modifier.nrows() ;
639 auto kcol = modifier.kcol() ;
640 auto dcol = modifier.dcol() ;
641 auto cols = modifier.cols() ;
642 auto values = modifier.data() ;
649 auto& local_row_size = matrix.getDistStructInfo().m_local_row_size;
651 for (std::size_t irow = 1; irow < nrows; ++irow)
653 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
658 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N});
659 Block2DType{values+k*NxN,N} = aik ;
660 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
662 for (
int j = k + 1; j < kcol[krow] + local_row_size[irow]; ++j)
665 int kj = m_work[jcol];
668 Block2DType{values+j*NxN,N} -= (aik * Block2DType{values+kj*NxN,N}) ;
671 for (
int l = kcol[krow]; l < kcol[krow] + local_row_size[krow]; ++l)
672 m_work[cols[l]] = -1;
678 op.recvLowerNeighbLUData(values);
679 int first_upper_ghost_index = matrix.getDistStructInfo().m_first_upper_ghost_index;
680 for (std::size_t irow = 1; irow < nrows; ++irow)
682 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
687 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N}) ;
688 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
690 for (
int j = k + 1; j < kcol[irow] + local_row_size[irow]; ++j)
693 int kj = m_work[jcol];
696 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
699 for (
int j = kcol[irow] + local_row_size[irow]; j < kcol[irow + 1]; ++j)
702 int kj = m_work[jcol];
703 if ((kj != -1) && (jcol >= first_upper_ghost_index)) {
705 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
708 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
709 m_work[cols[l]] = -1;
712 op.sendUpperNeighbLUData(values);
717 for (std::size_t irow = 1; irow < nrows; ++irow)
719 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
724 aik = Block2DType{values+k*NxN,N} * lu.inv(Block2DType{values+dcol[krow]*NxN,N}) ;
725 Block2DType{values+k*NxN,N} = aik ;
726 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
728 for (
int j = k + 1; j < kcol[irow + 1]; ++j)
731 int kj = m_work[jcol];
734 Block2DType{values+j*NxN,N} -= aik * Block2DType{values+kj*NxN,N} ;
737 for (
int l = kcol[krow]; l < kcol[krow + 1]; ++l)
738 m_work[cols[l]] = -1;
746 void blockSolveL(ValueType
const* y, ValueType* x)
const
748 if constexpr (MatrixType::on_host_only)
750#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
751 using namespace Eigen;
752 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
753 using Block2DView = Eigen::Map<Block2D> ;
754 using Block1D = Eigen::Matrix<ValueType,Dynamic,1> ;
755 using Block1DView = Eigen::Map<Block1D> ;
757 int N = m_block_size ;
765 auto nrows = view.nrows() ;
766 auto kcol = view.kcol() ;
767 auto dcol = view.dcol() ;
768 auto cols = view.cols() ;
769 auto values = view.data() ;
772 for (std::size_t irow = 0; irow < nrows; ++irow) {
774 val = Block1DView(
const_cast<ValueType*
>(y+irow*N),N) ;
775 for (
int k = kcol[irow]; k < dcol[irow]; ++k)
778 val -= Block2DView(
const_cast<ValueType*
>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
781 Block1DView(x+irow*N,N) = val ;
787 void blockSolveU(ValueType
const* y, ValueType* x)
const
789 if constexpr (MatrixType::on_host_only)
791#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
792 using namespace Eigen;
793 using Block2D = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
794 using Block2DView = Eigen::Map<Block2D> ;
795 using Block1D = Eigen::Matrix<ValueType,Dynamic,1> ;
796 using Block1DView = Eigen::Map<Block1D> ;
798 int N = m_block_size;
805 auto nrows = view.nrows() ;
806 auto kcol = view.kcol() ;
807 auto dcol = view.dcol() ;
808 auto cols = view.cols() ;
809 auto values = view.data() ;
812 auto& local_row_size = m_lu_matrix->getDistStructInfo().m_local_row_size;
813 for (
int irow = (
int)nrows - 1; irow > -1; --irow) {
816 val = Block1DView(
const_cast<ValueType*
>(y+irow*N),N) ;
817 for (
int k = dk + 1; k < kcol[irow] + local_row_size[irow]; ++k) {
819 val -= Block2DView(
const_cast<ValueType*
>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
823 Block1DView(x+irow*N,N) = m_inv_diag_matrix[irow].solve(val);
825 Block1DView(x+irow*N,N) = inv(Block2DView(
const_cast<ValueType*
>(values+dk*N2),N,N)) * val;
829 for (
int irow = (
int)nrows - 1; irow > -1; --irow) {
832 val = Block1DView(
const_cast<ValueType*
>(y+irow*N),N) ;
833 for (
int k = dk + 1; k < kcol[irow + 1]; ++k) {
835 val -= Block2DView(
const_cast<ValueType*
>(values+k*N2),N,N) * Block1DView(x+cols[k]*N,N) ;
839 Block1DView(x+irow*N,N) = m_inv_diag_matrix[irow].solve(val);
841 Block1DView(x+irow*N,N) = inv(Block2DView(
const_cast<ValueType*
>(values+dk*N2),N,N)) * val;
849 template <
typename AlgebraT>
850 void solve([[maybe_unused]] AlgebraT& algebra, VectorType
const& y, VectorType& x)
const
858 solveL(y.data(), m_x.data());
864 solveU(m_x.data(), x.data());
872 blockSolveL(y.data(), m_x.data());
878 blockSolveU(m_x.data(), x.data());
882 const MatrixType& getLUMatrix()
const
889 std::unique_ptr<MatrixType> m_lu_matrix ;
890 int m_block_size = 1;
891 ProfileType
const* m_profile =
nullptr;
892 mutable VectorType m_x ;
895 std::vector<int> m_work ;
896 std::size_t m_alloc_size = 0 ;
897 bool m_is_parallel = false ;
898 bool m_bjacobi = false ;
900 std::vector<int> m_send_lu_ibuffer ;
901 std::vector<std::vector<ValueType>> m_send_lu_buffer ;
903 bool m_use_inv_diag = true ;
904#if defined (ALIEN_USE_EIGEN3) && !defined(EIGEN3_DISABLED)
905 using EigenMatrix = Eigen::Matrix<ValueType,Eigen::Dynamic,Eigen::Dynamic,Eigen::RowMajor> ;
906 std::vector<Eigen::PartialPivLU<EigenMatrix>> m_inv_diag_matrix;