// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_LINSOLVE_WITH_FIXED_H #define IGL_LINSOLVE_WITH_FIXED_H #include "igl_inline.h" #define EIGEN_YES_I_KNOW_SPARSE_MODULE_IS_NOT_STABLE_YET #include #include #include #include // Bug in unsupported/Eigen/SparseExtra needs iostream first #include #include namespace igl { // LINSOLVE_WITH_FIXED Solves a sparse linear system Ax=b with // fixed known values in x // Templates: // T should be a eigen matrix primitive type like float or double // Inputs: // A m by n sparse matrix // b n by k dense matrix, k is bigger than 1 for multiple right handsides // known list of indices to known rows in x (must be sorted in ascending order) // Y list of fixed values corresponding to known rows in Z // Outputs: // x n by k dense matrix containing the solution template inline void SolveLinearSystemWithBoundaryConditions(const SparseMatrix& A, const MatrixBase& b, const vector& known, MatrixBase& x) { const int rows = x.rows(); const int cols = x.cols(); SparseMatrix AP(rows,rows); const int knownCount = known.size(); const int unknownCount = rows - knownCount; int knownIndex = 0; int unknownIndex = 0; if(knownCount >= rows) { std::cerr << "No unknowns to solve for!\n"; return; } // Permutate to sort by known boundary conditions -> [A1,A2] * [x1;x2] VectorXi transpositions; transpositions.resize(rows); for(int n=0;n P(transpositions); PermutationMatrix PInv = P.inverse(); A.twistedBy(PInv).evalTo(AP); // Split in kown and unknown parts A1,A2,x2,b1 SparseMatrix A1, A2; internal::plain_matrix_type::type x1, x2, b1; x2 = (PInv*x).block(unknownCount,0,knownCount,cols); b1 = (PInv*b).block(0,0,unknownCount,cols); SparseMatrix A1Temp(rows,unknownCount); SparseMatrix A2Temp(rows,knownCount); A1Temp = AP.innerVectors(0,unknownCount).transpose(); A2Temp = AP.innerVectors(unknownCount,knownCount).transpose(); A1 = A1Temp.innerVectors(0,unknownCount).transpose(); A2 = A2Temp.innerVectors(0,unknownCount).transpose(); // Solve A1*x1 = b - A2*x2 SparseLU> solver; solver.compute(A1); if (solver.info() != Eigen::Success) { std::cerr << "Matrix can not be decomposed.\n"; return; } internal::plain_matrix_type::type t = b1-A2*x2; x1 = solver.solve(t); if (solver.info() != Eigen::Success) { std::cerr << "Solving failed.\n"; return; } // Compose resulting x x.block(0,0,unknownCount,cols) = x1; x.block(unknownCount,0,knownCount,cols) = x2; x = P * x; }; }