/**
- * Return the nearest orthogonal matrix using a SVD if the
- * deteriminant is more than a tolerance away from one.
- * The orthogonalization is done by combining the products
- * of the SVD decomposition: $((U*I)*V^T)^T$, where I is the
- * idententy matrix and $U$ and $V$ are computed from the SVD
- * decomposition: $\mathbf U \cdot \mathbf S \cdot \mathbf V^T$
+ * Return the nearest orthogonal matrix using a SVD if the determinant is
+ * more than a tolerance away from one. The orthogonalization is done by
+ * combining the products of the SVD decomposition: $U V^T$, where
+ * $U$ and $V$ are computed from the SVD decomposition: $\mathbf U \mathbf S
+ * \mathbf V^T$, effectively replacing $\mathbf S$ with the identity matrix.
+ * @param tensor The tensor which to find the closest orthogonal
+ * tensor to.
+ * @param tolerance If the $\text{determinant} - 1$ is smaller than
+ * this value, it will just return the current tensor.
+ * Otherwise it will return the nearest orthogonal tensor.
* @relatesalso Tensor
*/
template <int dim, typename Number>
constexpr Tensor<2, dim, Number>
-orthogonalize(const Tensor<2, dim, Number> &tensor, const double tolerance)
+project_onto_orthogonal_tensors(const Tensor<2, dim, Number> &tensor,
+ const double tolerance)
{
if (std::abs(determinant(tensor) - 1.0) > tolerance)
{
- LAPACKFullMatrix<Number> identity_matrix(dim);
- for (size_t i = 0; i < dim; i++)
- {
- identity_matrix.set(i, i, 1.);
- }
-
Tensor<2, dim, Number> output_tensor;
FullMatrix<Number> matrix(dim);
LAPACKFullMatrix<Number> lapack_matrix(dim);
LAPACKFullMatrix<Number> result(dim);
- LAPACKFullMatrix<Number> result2(dim);
// todo: find or add dealii functionallity to copy in one step.
matrix.copy_from(tensor);
// now compute the svd of the matrices
lapack_matrix.compute_svd();
- // Use the SVD results to orthogonalize: ((U*I)*V^T)^T
- lapack_matrix.get_svd_u().mmult(result, identity_matrix);
- result.mmult(result2, (lapack_matrix.get_svd_vt()));
+ // Use the SVD results to orthogonalize: $U V^T$
+ lapack_matrix.get_svd_u().mmult(result, lapack_matrix.get_svd_vt());
// todo: find or add dealii functionallity to copy in one step.
- matrix = result2;
+ matrix = result;
matrix.copy_to(output_tensor);
return output_tensor;
}
const Tensor<2, dim, ADNumberType> C5 = A * a;
const Tensor<2, dim, ADNumberType> C6 = A / a;
- const ADNumberType det_A = determinant(A);
- const ADNumberType tr_A = trace(A);
- const Tensor<2, dim, ADNumberType> A_inv = invert(A);
- const Tensor<2, dim, ADNumberType> A_T = transpose(A);
- const Tensor<2, dim, ADNumberType> A_adj = adjugate(A);
- const Tensor<2, dim, ADNumberType> A_cof = cofactor(A);
- const Tensor<2, dim, ADNumberType> A_orth = orthogonalize(A);
- const ADNumberType A_l1_norm = l1_norm(A, 1e-8);
- const ADNumberType A_linf_norm = linfty_norm(A);
+ const ADNumberType det_A = determinant(A);
+ const ADNumberType tr_A = trace(A);
+ const Tensor<2, dim, ADNumberType> A_inv = invert(A);
+ const Tensor<2, dim, ADNumberType> A_T = transpose(A);
+ const Tensor<2, dim, ADNumberType> A_adj = adjugate(A);
+ const Tensor<2, dim, ADNumberType> A_cof = cofactor(A);
+ const Tensor<2, dim, ADNumberType> A_orth =
+ project_onto_orthogonal_tensors(A);
+ const ADNumberType A_l1_norm = l1_norm(A, 1e-8);
+ const ADNumberType A_linf_norm = linfty_norm(A);
const ADNumberType A_ddot_B = double_contract<0, 0, 1, 1>(A, B);
const Tensor<2, dim, ADNumberType> A_dot_B = contract<1, 0>(A, B);
DEAL_II_CONSTEXPR const auto dummy_8 = cofactor(a);
deallog << "Deteriminant before orthogonalization: " << determinant(a)
<< std::endl;
- const auto dummy_9 = orthogonalize(a, 1e-8);
+ const auto dummy_9 = project_onto_orthogonal_tensors(a, 1e-8);
deallog << "Deteriminant after orthogonalization: " << determinant(dummy_9)
<< std::endl;
Assert(determinant(dummy_9) - 1. < 1e-8, ExcInternalError());
deallog << "Deteriminant before orthogonalization: "
<< determinant(non_orthogonal) << std::endl;
- const auto dummy_10 = orthogonalize(non_orthogonal, 1e-8);
+ const auto dummy_10 = project_onto_orthogonal_tensors(non_orthogonal, 1e-8);
deallog << "Deteriminant after orthogonalization: "
<< determinant(dummy_10) << std::endl;
Assert(determinant(dummy_10) - 1. < 1e-8, ExcInternalError());