From 7356e7c5584914a9a5b168b024253e994eff439b Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Mon, 30 May 2011 08:50:32 +0000 Subject: [PATCH] get rid of the singular value decomposition altogether [[Imported from SVN: r7346]] --- dune/gfe/localgeodesicfefunction.hh | 52 ++++++++++++++++------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh index f987a13f..a8519b78 100644 --- a/dune/gfe/localgeodesicfefunction.hh +++ b/dune/gfe/localgeodesicfefunction.hh @@ -9,7 +9,6 @@ #include <dune/gfe/averagedistanceassembler.hh> #include <dune/gfe/targetspacertrsolver.hh> -#include <dune/gfe/svd.hh> #include <dune/gfe/tensor3.hh> //! calculates ret = A * B @@ -121,31 +120,38 @@ private: return result; } - static Dune::FieldMatrix<double,embeddedDim,embeddedDim> pseudoInverse(const Dune::FieldMatrix<double,embeddedDim,embeddedDim>& A) + static Dune::FieldMatrix<double,embeddedDim,embeddedDim> pseudoInverse(const Dune::FieldMatrix<double,embeddedDim,embeddedDim>& dFdq, + const TargetSpace& q) { - Dune::FieldMatrix<double,embeddedDim,embeddedDim> U = A; - Dune::FieldVector<double,embeddedDim> W; - Dune::FieldMatrix<double,embeddedDim,embeddedDim> V; - - svdcmp(U,W,V); - - // pseudoInv = V W^{-1} U^T - Dune::FieldMatrix<double,embeddedDim,embeddedDim> UT; + const int shortDim = TargetSpace::TangentVector::size; + + // the orthonormal frame + Dune::FieldMatrix<ctype,shortDim,embeddedDim> O = q.orthonormalFrame(); + + // compute A = O dFDq O^T + Dune::FieldMatrix<ctype,shortDim,shortDim> A; + for (int i=0; i<shortDim; i++) + for (int j=0; j<shortDim; j++) { + A[i][j] = 0; + for (int k=0; k<embeddedDim; k++) + for (int l=0; l<embeddedDim; l++) + A[i][j] += O[i][k]*dFdq[k][l]*O[j][l]; + } + A.invert(); + + Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> result; for (int i=0; i<embeddedDim; i++) - for (int j=0; j<embeddedDim; j++) - UT[i][j] = U[j][i]; - - for (int i=0; i<embeddedDim; i++) { - if (std::abs(W[i]) > 1e-12) // Diagonal may be zero, that's why we're using the pseudo inverse - UT[i] /= W[i]; - else - UT[i] = 0; - } - - return V*UT; + for (int j=0; j<embeddedDim; j++) { + result[i][j] = 0; + for (int k=0; k<shortDim; k++) + for (int l=0; l<shortDim; l++) + result[i][j] += O[k][i]*A[k][l]*O[l][j]; + } + + return result; } - + /** \brief Compute derivate of F(w,q) (the derivative of the weighted distance fctl) wrt to w */ Dune::FieldMatrix<ctype,embeddedDim,dim+1> computeDFdw(const TargetSpace& q) const { @@ -429,7 +435,7 @@ evaluateDerivativeOfGradientWRTCoefficient(const Dune::FieldVector<ctype, dim>& // dFDq is not invertible, if the target space is embedded into a higher-dimensional // Euclidean space. Therefore we use its pseudo inverse. I don't think that is the // best way, though. - Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdqPseudoInv = pseudoInverse(dFdq); + Dune::FieldMatrix<ctype,embeddedDim,embeddedDim> dFdqPseudoInv = pseudoInverse(dFdq,q); // Tensor3<double,embeddedDim,embeddedDim,embeddedDim> dvDqF -- GitLab