| 600 | } // factorizeBodyMobilityMatrix |
| 601 | |
| 602 | void |
| 603 | DirectMobilitySolver::factorizeDenseMatrix(double* mat_data, |
| 604 | const int mat_size, |
| 605 | const MobilityMatrixInverseType& inv_type, |
| 606 | int* ipiv, |
| 607 | const std::string& mat_name, |
| 608 | const std::string& err_msg) |
| 609 | { |
| 610 | using MatrixType = Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>; |
| 611 | Eigen::Map<MatrixType> mat_view(mat_data, Eigen::Index(mat_size), Eigen::Index(mat_size)); |
| 612 | |
| 613 | if (inv_type != LAPACK_LU) |
| 614 | { |
| 615 | // For compatibility with the old code, we copy the lower triangle into |
| 616 | // the upper triangle, even if they aren't actually equal |
| 617 | for (int i = 0; i < mat_size; ++i) |
| 618 | { |
| 619 | for (int j = i + 1; j < mat_size; ++j) |
| 620 | { |
| 621 | mat_view(i, j) = mat_view(j, i); |
| 622 | } |
| 623 | } |
| 624 | } |
| 625 | |
| 626 | if (inv_type == LAPACK_CHOLESKY) |
| 627 | { |
| 628 | Eigen::LLT<MatrixType> cholesky_factorization(mat_view); |
| 629 | mat_view = cholesky_factorization.matrixL(); |
| 630 | } |
| 631 | else if (inv_type == LAPACK_LU) |
| 632 | { |
| 633 | Eigen::PartialPivLU<MatrixType> plu_factorization(mat_view); |
| 634 | mat_view = plu_factorization.matrixLU(); |
| 635 | const auto& indices = plu_factorization.permutationP().indices(); |
| 636 | TBOX_ASSERT(indices.rows() * indices.cols() == mat_size); |
| 637 | std::copy_n(indices.data(), mat_size, ipiv); |
| 638 | } |
| 639 | else if (inv_type == LAPACK_SVD) |
| 640 | { |
| 641 | // Use the symmetric eigenvalue decomposition as a stand-in for the SVD. |
| 642 | // In particular, since A = V D V^T, where V is the matrix of eigenvectors |
| 643 | // and D is the matrix of eigenvalues, we can factorize A as |
| 644 | // |
| 645 | // A = V sqrt(D) sqrt(D) V^T |
| 646 | // = V sqrt(D) (V sqrt(D))^T |
| 647 | // |
| 648 | // and instead store A <- V sqrt(D) |
| 649 | Eigen::SelfAdjointEigenSolver<MatrixType> eigensolver(mat_view); |
| 650 | Eigen::Matrix<double, Eigen::Dynamic, 1> eigenvalues = eigensolver.eigenvalues(); |
| 651 | const MatrixType eigenvectors = eigensolver.eigenvectors(); |
| 652 | // Make negative eigenvalues to be equal to min eigen value from |
| 653 | // input option |
| 654 | int counter = 0, counter_zero = 0; |
| 655 | for (int i = 0; i < mat_size; ++i) |
| 656 | { |
| 657 | if (eigenvalues[i] < d_svd_eps) |
| 658 | { |
| 659 | eigenvalues[i] = d_svd_replace_value; |
nothing calls this directly
no test coverage detected