From d130b4d87837081806e8746582e1cc4b2db0d960 Mon Sep 17 00:00:00 2001 From: Oliver Sander <sander@igpm.rwth-aachen.de> Date: Sun, 1 May 2011 11:42:27 +0000 Subject: [PATCH] Implement method evaluateDerivative using the orthonormal frame instead of a singular value decomposition. This makes computing a Hesse matrix roughly 20% faster. [[Imported from SVN: r7232]] --- dune/gfe/localgeodesicfefunction.hh | 47 +++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/dune/gfe/localgeodesicfefunction.hh b/dune/gfe/localgeodesicfefunction.hh index e624d897..d8439808 100644 --- a/dune/gfe/localgeodesicfefunction.hh +++ b/dune/gfe/localgeodesicfefunction.hh @@ -251,22 +251,45 @@ evaluateDerivative(const Dune::FieldVector<ctype, dim>& local) const // //////////////////////////////////// // solve the system + // + // We want to solve + // dFdq * x = rhs + // However as dFdq is defined in the embedding space it has a positive rank. + // Hence we use the orthonormal frame at q to get rid of its kernel. + // That means we instead solve + // O dFdq O^T O x = O rhs // //////////////////////////////////// - - // 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); - + + 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]; + } + for (int i=0; i<dim; i++) { - - Dune::FieldVector<ctype,embeddedDim> rhs, x; + + Dune::FieldVector<ctype,embeddedDim> rhs; for (int j=0; j<embeddedDim; j++) rhs[j] = RHS[j][i]; - - //dFdq.solve(x, rhs); - dFdqPseudoInv.mv(rhs,x); - + + Dune::FieldVector<ctype,shortDim> shortRhs; + O.mv(rhs,shortRhs); + + Dune::FieldVector<ctype,shortDim> shortX; + A.solve(shortX,shortRhs); + + Dune::FieldVector<ctype,embeddedDim> x; + O.mtv(shortX,x); + for (int j=0; j<embeddedDim; j++) result[j][i] = x[j]; -- GitLab