From dcec0e99850702e641bd25e2999d5ee204e83240 Mon Sep 17 00:00:00 2001 From: Oliver Sander <oliver.sander@tu-dresden.de> Date: Thu, 1 Feb 2024 17:01:49 +0100 Subject: [PATCH] Make the local Hessian a local variable of the global assembler This will later simplify merging the mixed and non-mixed versions of the assembler code. --- dune/gfe/assemblers/geodesicfeassembler.hh | 5 ++-- .../localgeodesicfeadolcstiffness.hh | 16 +++++----- .../assemblers/localgeodesicfefdstiffness.hh | 14 +++++---- .../assemblers/localgeodesicfestiffness.hh | 7 ++--- dune/gfe/assemblers/mixedgfeassembler.hh | 20 +++++++++---- .../mixedlocalgeodesicfestiffness.hh | 18 +++++++----- .../assemblers/mixedlocalgfeadolcstiffness.hh | 29 +++++++++++-------- test/adolctest.cc | 8 +++-- 8 files changed, 69 insertions(+), 48 deletions(-) diff --git a/dune/gfe/assemblers/geodesicfeassembler.hh b/dune/gfe/assemblers/geodesicfeassembler.hh index f75264cf..467db9e3 100644 --- a/dune/gfe/assemblers/geodesicfeassembler.hh +++ b/dune/gfe/assemblers/geodesicfeassembler.hh @@ -168,9 +168,10 @@ assembleGradientAndHessian(const std::vector<TargetSpace>& sol, localSolution[i] = sol[localView.index(i)]; std::vector<Dune::FieldVector<double,blocksize> > localGradient(numOfBaseFct); + Dune::Matrix<Dune::FieldMatrix<double,blocksize,blocksize> > localHessian(numOfBaseFct,numOfBaseFct); // setup local matrix and gradient - localStiffness_->assembleGradientAndHessian(localView, localSolution, localGradient); + localStiffness_->assembleGradientAndHessian(localView, localSolution, localGradient, localHessian); // Add element matrix to global stiffness matrix for(int i=0; i<numOfBaseFct; i++) { @@ -180,7 +181,7 @@ assembleGradientAndHessian(const std::vector<TargetSpace>& sol, for (int j=0; j<numOfBaseFct; j++ ) { auto col = localView.index(j); - hessian[row][col] += localStiffness_->A_[i][j]; + hessian[row][col] += localHessian[i][j]; } } diff --git a/dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh b/dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh index 49937c2c..74565e23 100644 --- a/dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh +++ b/dune/gfe/assemblers/localgeodesicfeadolcstiffness.hh @@ -47,7 +47,7 @@ public: /** \brief Compute the energy at the current configuration */ virtual RT energy (const typename Basis::LocalView& localView, - const std::vector<TargetSpace>& localSolution) const; + const std::vector<TargetSpace>& localSolution) const override; /** \brief Assemble the element gradient of the energy functional @@ -55,7 +55,7 @@ public: */ virtual void assembleGradient(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& solution, - std::vector<typename TargetSpace::TangentVector>& gradient) const; + std::vector<typename TargetSpace::TangentVector>& gradient) const override; /** \brief Assemble the local stiffness matrix at the current position @@ -63,7 +63,8 @@ public: */ virtual void assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localSolution, - std::vector<typename TargetSpace::TangentVector>& localGradient); + std::vector<typename TargetSpace::TangentVector>& localGradient, + Dune::Matrix<Dune::FieldMatrix<RT,blocksize,blocksize> >& localHessian) const override; const Dune::GFE::LocalEnergy<Basis, ATargetSpace>* localEnergy_; const bool adolcScalarMode_; @@ -166,7 +167,8 @@ template <class Basis, class TargetSpace> void LocalGeodesicFEADOLCStiffness<Basis, TargetSpace>:: assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localSolution, - std::vector<typename TargetSpace::TangentVector>& localGradient) + std::vector<typename TargetSpace::TangentVector>& localGradient, + Dune::Matrix<Dune::FieldMatrix<RT,blocksize,blocksize> >& localHessian) const { // Tape energy computation. We may not have to do this every time, but it's comparatively cheap. energy(localView, localSolution); @@ -302,7 +304,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, typedef typename TargetSpace::EmbeddedTangentVector EmbeddedTangentVector; typedef typename TargetSpace::TangentVector TangentVector; - this->A_.setSize(nDofs,nDofs); + localHessian.setSize(nDofs,nDofs); for (size_t col=0; col<nDofs; col++) { @@ -316,7 +318,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, embeddedHessian[row][col].mv(z,semiEmbeddedProduct); for (int subRow=0; subRow<blocksize; subRow++) - this->A_[row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; + localHessian[row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; } } @@ -343,7 +345,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, TangentVector tmp2; orthonormalFrame[row].mv(tmp1,tmp2); - this->A_[row][row][subRow] += tmp2; + localHessian[row][row][subRow] += tmp2; } } diff --git a/dune/gfe/assemblers/localgeodesicfefdstiffness.hh b/dune/gfe/assemblers/localgeodesicfefdstiffness.hh index fd2a36c4..442fc88b 100644 --- a/dune/gfe/assemblers/localgeodesicfefdstiffness.hh +++ b/dune/gfe/assemblers/localgeodesicfefdstiffness.hh @@ -55,7 +55,8 @@ public: */ virtual void assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localSolution, - std::vector<typename TargetSpace::TangentVector>& localGradient) override; + std::vector<typename TargetSpace::TangentVector>& localGradient, + typename Dune::GFE::Impl::LocalStiffnessTypes<TargetSpace>::Hessian& localHessian) const override; const Dune::GFE::LocalEnergy<Basis, ATargetSpace>* localEnergy_; @@ -131,15 +132,16 @@ template <class Basis, class TargetSpace, class field_type> void LocalGeodesicFEFDStiffness<Basis, TargetSpace, field_type>:: assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localSolution, - std::vector<typename TargetSpace::TangentVector>& localGradient) + std::vector<typename TargetSpace::TangentVector>& localGradient, + typename Dune::GFE::Impl::LocalStiffnessTypes<TargetSpace>::Hessian& localHessian) const { // Number of degrees of freedom for this element size_t nDofs = localSolution.size(); // Clear assemble data - this->A_.setSize(nDofs, nDofs); + localHessian.setSize(nDofs, nDofs); - this->A_ = 0; + localHessian = 0; #ifdef MULTIPRECISION const field_type eps = 1e-10; @@ -245,9 +247,9 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, field_type foo = 0.5 * (forwardValue - 2*centerValue + backwardValue) / (eps*eps); #ifdef MULTIPRECISION - this->A_[i][j][i2][j2] = this->A_[j][i][j2][i2] = foo.template convert_to<double>(); + localHessian[i][j][i2][j2] = localHessian[j][i][j2][i2] = foo.template convert_to<double>(); #else - this->A_[i][j][i2][j2] = this->A_[j][i][j2][i2] = foo; + localHessian[i][j][i2][j2] = localHessian[j][i][j2][i2] = foo; #endif } } diff --git a/dune/gfe/assemblers/localgeodesicfestiffness.hh b/dune/gfe/assemblers/localgeodesicfestiffness.hh index 24dab769..389caf17 100644 --- a/dune/gfe/assemblers/localgeodesicfestiffness.hh +++ b/dune/gfe/assemblers/localgeodesicfestiffness.hh @@ -26,7 +26,8 @@ public: */ virtual void assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localSolution, - std::vector<typename TargetSpace::TangentVector>& localGradient) = 0; + std::vector<typename TargetSpace::TangentVector>& localGradient, + Dune::Matrix<Dune::FieldMatrix<RT,blocksize,blocksize> >& localHessian) const = 0; /** \brief Compute the energy at the current configuration */ virtual RT energy (const typename Basis::LocalView& localView, @@ -37,10 +38,6 @@ public: virtual void assembleGradient(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& solution, std::vector<typename TargetSpace::TangentVector>& gradient) const = 0; - - // assembled data - Dune::Matrix<Dune::FieldMatrix<RT,blocksize,blocksize> > A_; - }; #endif diff --git a/dune/gfe/assemblers/mixedgfeassembler.hh b/dune/gfe/assemblers/mixedgfeassembler.hh index ebfe80f2..d7f111df 100644 --- a/dune/gfe/assemblers/mixedgfeassembler.hh +++ b/dune/gfe/assemblers/mixedgfeassembler.hh @@ -194,10 +194,20 @@ assembleGradientAndHessian(const std::vector<TargetSpace0>& configuration0, std::vector<Dune::FieldVector<double,blocksize0> > localGradient0(nDofs0); std::vector<Dune::FieldVector<double,blocksize1> > localGradient1(nDofs1); + using Row0 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<double, blocksize0, blocksize0> >, + Dune::Matrix<Dune::FieldMatrix<double, blocksize0, blocksize1> > >; + using Row1 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<double, blocksize1, blocksize0> >, + Dune::Matrix<Dune::FieldMatrix<double, blocksize1, blocksize1> > >; + + using HessianType = Dune::MultiTypeBlockMatrix<Row0, Row1>; + + HessianType localHessian; + // setup local matrix and gradient localStiffness_->assembleGradientAndHessian(localView, localConfiguration0, localConfiguration1, - localGradient0, localGradient1); + localGradient0, localGradient1, + localHessian); // Add element matrix to global stiffness matrix for (int i=0; i<nDofs0+nDofs1; i++) @@ -227,16 +237,16 @@ assembleGradientAndHessian(const std::vector<TargetSpace0>& configuration0, auto col = localView.index(localIndexCol); if (row[0]==0 and col[0]==0) - hessian[_0][_0][row[1]][col[1]] += localStiffness_->A_[_0][_0][i][j]; + hessian[_0][_0][row[1]][col[1]] += localHessian[_0][_0][i][j]; if (row[0]==0 and col[0]==1) - hessian[_0][_1][row[1]][col[1]] += localStiffness_->A_[_0][_1][i][j-nDofs0]; + hessian[_0][_1][row[1]][col[1]] += localHessian[_0][_1][i][j-nDofs0]; if (row[0]==1 and col[0]==0) - hessian[_1][_0][row[1]][col[1]] += localStiffness_->A_[_1][_0][i-nDofs0][j]; + hessian[_1][_0][row[1]][col[1]] += localHessian[_1][_0][i-nDofs0][j]; if (row[0]==1 and col[0]==1) - hessian[_1][_1][row[1]][col[1]] += localStiffness_->A_[_1][_1][i-nDofs0][j-nDofs0]; + hessian[_1][_1][row[1]][col[1]] += localHessian[_1][_1][i-nDofs0][j-nDofs0]; } // Add local gradient to global gradient diff --git a/dune/gfe/assemblers/mixedlocalgeodesicfestiffness.hh b/dune/gfe/assemblers/mixedlocalgeodesicfestiffness.hh index b74d94fb..7175a144 100644 --- a/dune/gfe/assemblers/mixedlocalgeodesicfestiffness.hh +++ b/dune/gfe/assemblers/mixedlocalgeodesicfestiffness.hh @@ -26,13 +26,22 @@ public: constexpr static int blocksize0 = DeformationTargetSpace::TangentVector::dimension; constexpr static int blocksize1 = OrientationTargetSpace::TangentVector::dimension; + // Type of the local Hessian + using Row0 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<RT, blocksize0, blocksize0> >, + Dune::Matrix<Dune::FieldMatrix<RT, blocksize0, blocksize1> > >; + using Row1 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<RT, blocksize1, blocksize0> >, + Dune::Matrix<Dune::FieldMatrix<RT, blocksize1, blocksize1> > >; + + using HessianType = Dune::MultiTypeBlockMatrix<Row0, Row1>; + /** \brief Assemble the local stiffness matrix at the current position */ virtual void assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<DeformationTargetSpace>& localDisplacementConfiguration, const std::vector<OrientationTargetSpace>& localOrientationConfiguration, std::vector<typename DeformationTargetSpace::TangentVector>& localDeformationGradient, - std::vector<typename OrientationTargetSpace::TangentVector>& localOrientationGradient) + std::vector<typename OrientationTargetSpace::TangentVector>& localOrientationGradient, + HessianType& hessian) { DUNE_THROW(Dune::NotImplemented, "!"); } @@ -42,13 +51,6 @@ public: const std::vector<DeformationTargetSpace>& localDeformationConfiguration, const std::vector<OrientationTargetSpace>& localOrientationConfiguration) const = 0; - // assembled tangent matrix - using Row0 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<RT, blocksize0, blocksize0> >, - Dune::Matrix<Dune::FieldMatrix<RT, blocksize0, blocksize1> > >; - using Row1 = Dune::MultiTypeBlockVector<Dune::Matrix<Dune::FieldMatrix<RT, blocksize1, blocksize0> >, - Dune::Matrix<Dune::FieldMatrix<RT, blocksize1, blocksize1> > >; - - Dune::MultiTypeBlockMatrix<Row0, Row1> A_; }; #endif diff --git a/dune/gfe/assemblers/mixedlocalgfeadolcstiffness.hh b/dune/gfe/assemblers/mixedlocalgfeadolcstiffness.hh index 603cb811..f30ff1df 100644 --- a/dune/gfe/assemblers/mixedlocalgfeadolcstiffness.hh +++ b/dune/gfe/assemblers/mixedlocalgfeadolcstiffness.hh @@ -34,6 +34,9 @@ class MixedLocalGFEADOLCStiffness // some other sizes constexpr static int gridDim = GridView::dimension; + using Base = MixedLocalGeodesicFEStiffness<Basis,Dune::GFE::ProductManifold<TargetSpace0,TargetSpace1> >; + using HessianType = typename Base::HessianType; + public: //! Dimension of a tangent space @@ -63,7 +66,8 @@ public: const std::vector<TargetSpace0>& localConfiguration0, const std::vector<TargetSpace1>& localConfiguration1, std::vector<typename TargetSpace0::TangentVector>& localGradient0, - std::vector<typename TargetSpace1::TangentVector>& localGradient1) override; + std::vector<typename TargetSpace1::TangentVector>& localGradient1, + HessianType& localHessian) override; const MixedLocalGeodesicFEStiffness<Basis, Dune::GFE::ProductManifold<ATargetSpace0, ATargetSpace1> >* localEnergy_; const bool adolcScalarMode_; @@ -140,7 +144,8 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, const std::vector<TargetSpace0>& localConfiguration0, const std::vector<TargetSpace1>& localConfiguration1, std::vector<typename TargetSpace0::TangentVector>& localGradient0, - std::vector<typename TargetSpace1::TangentVector>& localGradient1) + std::vector<typename TargetSpace1::TangentVector>& localGradient1, + HessianType& localHessian) { int rank = Dune::MPIHelper::getCommunication().rank(); // Tape energy computation. We may not have to do this every time, but it's comparatively cheap. @@ -353,7 +358,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, using namespace Dune::Indices; - this->A_[_0][_0].setSize(nDofs0,nDofs0); + localHessian[_0][_0].setSize(nDofs0,nDofs0); for (size_t col=0; col<nDofs0; col++) { @@ -367,14 +372,14 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, embeddedHessian00[row][col].mv(z,semiEmbeddedProduct); for (int subRow=0; subRow<blocksize0; subRow++) - this->A_[_0][_0][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; + localHessian[_0][_0][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; } } } - this->A_[_0][_1].setSize(nDofs0,nDofs1); + localHessian[_0][_1].setSize(nDofs0,nDofs1); for (size_t col=0; col<nDofs1; col++) { @@ -388,14 +393,14 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, embeddedHessian01[row][col].mv(z,semiEmbeddedProduct); for (int subRow=0; subRow<blocksize0; subRow++) - this->A_[_0][_1][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; + localHessian[_0][_1][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; } } } - this->A_[_1][_0].setSize(nDofs1,nDofs0); + localHessian[_1][_0].setSize(nDofs1,nDofs0); for (size_t col=0; col<nDofs0; col++) { @@ -409,14 +414,14 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, embeddedHessian10[row][col].mv(z,semiEmbeddedProduct); for (int subRow=0; subRow<blocksize1; subRow++) - this->A_[_1][_0][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; + localHessian[_1][_0][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; } } } - this->A_[_1][_1].setSize(nDofs1,nDofs1); + localHessian[_1][_1].setSize(nDofs1,nDofs1); for (size_t col=0; col<nDofs1; col++) { @@ -430,7 +435,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, embeddedHessian11[row][col].mv(z,semiEmbeddedProduct); for (int subRow=0; subRow<blocksize1; subRow++) - this->A_[_1][_1][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; + localHessian[_1][_1][row][col][subRow][subCol] = semiEmbeddedProduct[subRow]; } } @@ -462,7 +467,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, typename TargetSpace0::TangentVector tmp2; orthonormalFrame0[row].mv(tmp1,tmp2); - this->A_[_0][_0][row][row][subRow] += tmp2; + localHessian[_0][_0][row][row][subRow] += tmp2; } } @@ -477,7 +482,7 @@ assembleGradientAndHessian(const typename Basis::LocalView& localView, typename TargetSpace1::TangentVector tmp2; orthonormalFrame1[row].mv(tmp1,tmp2); - this->A_[_1][_1][row][row][subRow] += tmp2; + localHessian[_1][_1][row][row][subRow] += tmp2; } } diff --git a/test/adolctest.cc b/test/adolctest.cc index d53f84b7..8b59ac4e 100644 --- a/test/adolctest.cc +++ b/test/adolctest.cc @@ -580,14 +580,16 @@ int main (int argc, char *argv[]) try localGFEADOLCStiffness.assembleGradientAndHessian(localView, localSolution, - localRiemannianADGradient); + localRiemannianADGradient, + localRiemannianADHessian); localGFEFDStiffness.assembleGradientAndHessian(localView, localSolution, - localRiemannianFDGradient); + localRiemannianFDGradient, + localRiemannianFDHessian); // compare - compareMatrices(localGFEADOLCStiffness.A_, "Riemannian AD", localGFEFDStiffness.A_, "Riemannian FD"); + compareMatrices(localRiemannianADHessian, "Riemannian AD", localRiemannianFDHessian, "Riemannian FD"); } -- GitLab