10 Eigen::FullPivLU<Eigen::MatrixXd> lu(M);
11 Eigen::JacobiSVD<Eigen::MatrixXd> svd(M);
12 double s1 = svd.singularValues()(0);
13 double s2 = svd.singularValues()(svd.singularValues().size() - 1);
14 double cond = s1 / s2;
16 logger().trace(
"----------------------------------------");
17 logger().trace(
"-- Determinant: {}", M.determinant());
18 logger().trace(
"-- Singular values: {} {}", s1, s2);
19 logger().trace(
"-- Cond: {}", cond);
20 logger().trace(
"-- Invertible: {}", lu.isInvertible());
21 logger().trace(
"----------------------------------------");
27 inline bool nanproof_equals(
const double x,
const double y)
29 return x ==
y || (std::isnan(
x) == std::isnan(
y));
37 return Eigen::VectorXd();
39 Eigen::VectorXd
x(X.size());
40 for (
int i = 0; i < X.rows(); ++i)
42 for (
int j = 0; j < X.cols(); ++j)
44 x(i * X.cols() + j) = X(i, j);
47 assert(nanproof_equals(X(0, 0),
x(0)));
48 assert(X.cols() <= 1 || nanproof_equals(X(0, 1),
x(1)));
56 return Eigen::MatrixXd(0, dim);
58 assert(
x.size() % dim == 0);
59 Eigen::MatrixXd X(
x.size() / dim, dim);
60 for (
int i = 0; i <
x.size(); ++i)
62 X(i / dim, i % dim) =
x(i);
64 assert(nanproof_equals(X(0, 0),
x(0)));
65 assert(X.cols() <= 1 || nanproof_equals(X(0, 1),
x(1)));
74 else if (
vec.size() == 4)
77 throw std::runtime_error(
"Invalid size in vector2matrix!");
79 assert(size * size ==
vec.size());
86 std::vector<Eigen::Triplet<double>> triplets;
88 for (
int k = 0; k < M.outerSize(); ++k)
90 for (Eigen::SparseMatrix<double>::InnerIterator it(M, k); it; ++it)
92 triplets.emplace_back(it.row(), it.row(), it.value());
96 Eigen::SparseMatrix<double> lumped(M.rows(), M.rows());
97 lumped.setFromTriplets(triplets.begin(), triplets.end());
98 lumped.makeCompressed();
105 const int reduced_size,
106 const std::vector<int> &removed_vars,
112 if (reduced_size == full_size || reduced_size == full.rows())
114 assert(reduced_size == full.rows() && reduced_size == full.cols());
118 assert(full.rows() == full_size && full.cols() == full_size);
120 Eigen::VectorXi indices(full_size);
123 for (
int i = 0; i < full_size; ++i)
125 if (kk < removed_vars.size() && removed_vars[kk] == i)
132 indices(i) = index++;
135 assert(index == reduced_size);
137 std::vector<Eigen::Triplet<double>>
entries;
138 entries.reserve(full.nonZeros());
139 for (
int k = 0; k < full.outerSize(); ++k)
144 for (StiffnessMatrix::InnerIterator it(full, k); it; ++it)
146 assert(it.col() == k);
147 if (indices(it.row()) < 0 || indices(it.col()) < 0)
150 assert(indices(it.row()) >= 0);
151 assert(indices(it.col()) >= 0);
153 entries.emplace_back(indices(it.row()), indices(it.col()), it.value());
157 reduced.resize(reduced_size, reduced_size);
159 reduced.makeCompressed();
163 const Eigen::MatrixXd &in,
164 const Eigen::VectorXi &in_to_out,
166 const int block_size)
168 constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
170 assert(in.rows() % block_size == 0);
171 assert(in_to_out.size() == in.rows() / block_size);
174 out_blocks = in.rows() / block_size;
176 Eigen::MatrixXd out = Eigen::MatrixXd::Constant(
177 out_blocks * block_size, in.cols(), NaN);
179 const int in_blocks = in.rows() / block_size;
180 for (
int i = 0; i < in_blocks; ++i)
182 const int j = in_to_out[i];
186 out.middleRows(block_size * j, block_size) =
187 in.middleRows(block_size * i, block_size);
194 const Eigen::MatrixXd &out,
195 const Eigen::VectorXi &in_to_out,
197 const int block_size)
199 constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
201 assert(out.rows() % block_size == 0);
204 in_blocks = out.rows() / block_size;
205 assert(in_to_out.size() == in_blocks);
207 Eigen::MatrixXd in = Eigen::MatrixXd::Constant(
208 in_blocks * block_size, out.cols(), NaN);
210 for (
int i = 0; i < in_blocks; i++)
212 const int j = in_to_out[i];
216 in.middleRows(block_size * i, block_size) =
217 out.middleRows(block_size * j, block_size);
224 const Eigen::MatrixXi &in,
225 const Eigen::VectorXi &index_mapping)
227 Eigen::MatrixXi out(in.rows(), in.cols());
228 for (
int i = 0; i < in.rows(); i++)
230 for (
int j = 0; j < in.cols(); j++)
232 out(i, j) = index_mapping[in(i, j)];
std::vector< Eigen::Triplet< double > > entries
#define POLYFEM_SCOPED_TIMER(...)
Eigen::SparseMatrix< double > lump_matrix(const Eigen::SparseMatrix< double > &M)
Lump each row of a matrix into the diagonal.
void show_matrix_stats(const Eigen::MatrixXd &M)
Eigen::MatrixXd reorder_matrix(const Eigen::MatrixXd &in, const Eigen::VectorXi &in_to_out, int out_blocks=-1, const int block_size=1)
Reorder row blocks in a matrix.
void vector2matrix(const Eigen::VectorXd &vec, Eigen::MatrixXd &mat)
Eigen::MatrixXd unreorder_matrix(const Eigen::MatrixXd &out, const Eigen::VectorXi &in_to_out, int in_blocks=-1, const int block_size=1)
Undo the reordering of row blocks in a matrix.
Eigen::MatrixXd unflatten(const Eigen::VectorXd &x, int dim)
Unflatten rowwises, so every dim elements in x become a row.
Eigen::VectorXd flatten(const Eigen::MatrixXd &X)
Flatten rowwises.
Eigen::MatrixXi map_index_matrix(const Eigen::MatrixXi &in, const Eigen::VectorXi &index_mapping)
Map the entrys of an index matrix to new indices.
void full_to_reduced_matrix(const int full_size, const int reduced_size, const std::vector< int > &removed_vars, const StiffnessMatrix &full, StiffnessMatrix &reduced)
Map a full size matrix to a reduced one by dropping rows and columns.
spdlog::logger & logger()
Retrieves the current logger.
Eigen::SparseMatrix< double, Eigen::ColMajor > StiffnessMatrix