diff --git a/dune/gfe/rodlocalstiffness.hh b/dune/gfe/rodlocalstiffness.hh index f5a8b6735b588aca9f97ab3686f836e72194c2b7..b95578d820cbe2de26a9383ef8ef8ee31bfe74d1 100644 --- a/dune/gfe/rodlocalstiffness.hh +++ b/dune/gfe/rodlocalstiffness.hh @@ -4,6 +4,11 @@ #include <array> #include <dune/common/fmatrix.hh> +#include <dune/common/version.hh> +#if DUNE_VERSION_GTE(DUNE_COMMON, 2, 8) +#include <dune/common/transpose.hh> +#endif + #include <dune/istl/matrix.hh> #include <dune/geometry/quadraturerules.hh> @@ -11,12 +16,13 @@ #include <dune/fufem/boundarypatch.hh> -#include <dune/gfe/localfirstordermodel.hh> +#include <dune/gfe/localenergy.hh> +#include <dune/gfe/localgeodesicfefunction.hh> #include "rigidbodymotion.hh" template<class GridView, class RT> class RodLocalStiffness -: public Dune::GFE::LocalFirstOrderModel<Dune::Functions::LagrangeBasis<GridView,1>, RigidBodyMotion<RT,3> > +: public Dune::GFE::LocalEnergy<Dune::Functions::LagrangeBasis<GridView,1>, RigidBodyMotion<RT,3> > { typedef RigidBodyMotion<RT,3> TargetSpace; typedef Dune::Functions::LagrangeBasis<GridView,1> Basis; @@ -36,8 +42,14 @@ class RodLocalStiffness public: - /** \brief The stress-free configuration */ - std::vector<RigidBodyMotion<RT,3> > referenceConfiguration_; + /** \brief The stress-free configuration + + The number type cannot be RT, because RT become `adouble` when + using RodLocalStiffness together with an AD system. + The referenceConfiguration is not a variable, and we don't + want to use `adouble` for it. + */ + std::vector<RigidBodyMotion<double,3> > referenceConfiguration_; public: @@ -94,7 +106,7 @@ public: - void setReferenceConfiguration(const std::vector<RigidBodyMotion<RT,3> >& referenceConfiguration) { + void setReferenceConfiguration(const std::vector<RigidBodyMotion<double,3> >& referenceConfiguration) { referenceConfiguration_ = referenceConfiguration; } @@ -102,18 +114,21 @@ public: virtual RT energy (const typename Basis::LocalView& localView, const std::vector<RigidBodyMotion<RT,3> >& localSolution) const override; - /** \brief Assemble the element gradient of the energy functional */ - void assembleGradient(const typename Basis::LocalView& localView, - const std::vector<RigidBodyMotion<RT,3> >& solution, - std::vector<Dune::FieldVector<double,6> >& gradient) const override; - - /** \brief Get strain at one point of the domain */ - Dune::FieldVector<double, 6> getStrain(const std::vector<RigidBodyMotion<RT,3> >& localSolution, + /** \brief Get the rod strain at one point in the rod + * + * \tparam Number This is a member template because the method has to work for double and adouble + */ + template<class Number> + Dune::FieldVector<Number, 6> getStrain(const std::vector<RigidBodyMotion<Number,3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const; - /** \brief Get stress at one point of the domain */ - Dune::FieldVector<RT, 6> getStress(const std::vector<RigidBodyMotion<RT,3> >& localSolution, + /** \brief Get the rod stress at one point in the rod + * + * \tparam Number This is a member template because the method has to work for double and adouble + */ + template<class Number> + Dune::FieldVector<Number, 6> getStress(const std::vector<RigidBodyMotion<Number,3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const; @@ -135,7 +150,7 @@ public: protected: void getLocalReferenceConfiguration(const Entity& element, - std::vector<RigidBodyMotion<RT,3> >& localReferenceConfiguration) const { + std::vector<RigidBodyMotion<double,3> >& localReferenceConfiguration) const { unsigned int numOfBaseFct = element.subEntities(dim); localReferenceConfiguration.resize(numOfBaseFct); @@ -144,18 +159,10 @@ protected: localReferenceConfiguration[i] = referenceConfiguration_[gridView_.indexSet().subIndex(element,i,dim)]; } -public: - static void interpolationDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& q1, double s, - std::array<Quaternion<double>,6>& grad); - - static void interpolationVelocityDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& q1, double s, - double intervalLength, std::array<Quaternion<double>,6>& grad); - -protected: - template <class T> + template <class T> static Dune::FieldVector<T,3> darboux(const Rotation<T,3>& q, const Dune::FieldVector<T,4>& q_s) { - Dune::FieldVector<double,3> u; // The Darboux vector + Dune::FieldVector<T,3> u; // The Darboux vector u[0] = 2 * (q.B(0) * q_s); u[1] = 2 * (q.B(1) * q_s); @@ -176,7 +183,7 @@ energy(const typename Basis::LocalView& localView, RT energy = 0; - std::vector<RigidBodyMotion<RT,3> > localReferenceConfiguration; + std::vector<RigidBodyMotion<double,3> > localReferenceConfiguration; getLocalReferenceConfiguration(element, localReferenceConfiguration); // /////////////////////////////////////////////////////////////////////////////// @@ -200,10 +207,10 @@ energy(const typename Basis::LocalView& localView, double weight = shearingQuad[pt].weight() * integrationElement; - Dune::FieldVector<double,6> strain = getStrain(localSolutionVector, element, quadPos); + auto strain = getStrain(localSolutionVector, element, quadPos); // The reference strain - Dune::FieldVector<double,6> referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); + auto referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); for (int i=0; i<3; i++) energy += weight * 0.5 * A_[i] * (strain[i] - referenceStrain[i]) * (strain[i] - referenceStrain[i]); @@ -221,10 +228,10 @@ energy(const typename Basis::LocalView& localView, double weight = bendingQuad[pt].weight() * element.geometry().integrationElement(quadPos); - Dune::FieldVector<double,6> strain = getStrain(localSolutionVector, element, quadPos); + auto strain = getStrain(localSolutionVector, element, quadPos); // The reference strain - Dune::FieldVector<double,6> referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); + auto referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); // Part II: the bending and twisting energy for (int i=0; i<3; i++) @@ -237,219 +244,9 @@ energy(const typename Basis::LocalView& localView, template <class GridView, class RT> -void RodLocalStiffness<GridView, RT>:: -interpolationDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& q1, double s, - std::array<Quaternion<double>,6>& grad) -{ - // Clear output array - for (int i=0; i<6; i++) - grad[i] = 0; - - // The derivatives with respect to w^0 - - // Compute q_1^{-1}q_0 - Rotation<RT,3> q1InvQ0 = q1; - q1InvQ0.invert(); - q1InvQ0 = q1InvQ0.mult(q0); - - { - // Compute v = (1-s) \exp^{-1} ( q_1^{-1} q_0) - Dune::FieldVector<RT,3> v = Rotation<RT,3>::expInv(q1InvQ0); - v *= (1-s); - - Dune::FieldMatrix<RT,4,3> dExp_v = Rotation<RT,3>::Dexp(SkewMatrix<RT,3>(v)); - - Dune::FieldMatrix<RT,3,4> dExpInv = Rotation<RT,3>::DexpInv(q1InvQ0); - - Dune::FieldMatrix<RT,4,4> mat(0); - for (int i=0; i<4; i++) - for (int j=0; j<4; j++) - for (int k=0; k<3; k++) - mat[i][j] += (1-s) * dExp_v[i][k] * dExpInv[k][j]; - - for (int i=0; i<3; i++) { - - Quaternion<RT> dw; - for (int j=0; j<4; j++) - dw[j] = 0.5 * (i==j); // dExp[j][i] at v=0 - - dw = q1InvQ0.Quaternion<double>::mult(dw); - - mat.umv(dw,grad[i]); - grad[i] = q1.Quaternion<double>::mult(grad[i]); - - } - } - - - // The derivatives with respect to w^1 - - // Compute q_0^{-1} - Rotation<RT,3> q0InvQ1 = q0; - q0InvQ1.invert(); - q0InvQ1 = q0InvQ1.mult(q1); - - { - // Compute v = s \exp^{-1} ( q_0^{-1} q_1) - Dune::FieldVector<RT,3> v = Rotation<RT,3>::expInv(q0InvQ1); - v *= s; - - Dune::FieldMatrix<RT,4,3> dExp_v = Rotation<RT,3>::Dexp(SkewMatrix<RT,3>(v)); - - Dune::FieldMatrix<RT,3,4> dExpInv = Rotation<RT,3>::DexpInv(q0InvQ1); - - Dune::FieldMatrix<RT,4,4> mat(0); - for (int i=0; i<4; i++) - for (int j=0; j<4; j++) - for (int k=0; k<3; k++) - mat[i][j] += s * dExp_v[i][k] * dExpInv[k][j]; - - for (int i=3; i<6; i++) { - - Quaternion<RT> dw; - for (int j=0; j<4; j++) - dw[j] = 0.5 * ((i-3)==j); // dExp[j][i-3] at v=0 - - dw = q0InvQ1.Quaternion<double>::mult(dw); - - mat.umv(dw,grad[i]); - grad[i] = q0.Quaternion<double>::mult(grad[i]); - - } - } -} - - - -template <class GridView, class RT> -void RodLocalStiffness<GridView, RT>:: -interpolationVelocityDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& q1, double s, - double intervalLength, std::array<Quaternion<double>,6>& grad) -{ - // Clear output array - for (int i=0; i<6; i++) - grad[i] = 0; - - // Compute q_0^{-1} - Rotation<RT,3> q0Inv = q0; - q0Inv.invert(); - - - // Compute v = s \exp^{-1} ( q_0^{-1} q_1) - Dune::FieldVector<RT,3> v = Rotation<RT,3>::expInv(q0Inv.mult(q1)); - v *= s/intervalLength; - - Dune::FieldMatrix<RT,4,3> dExp_v = Rotation<RT,3>::Dexp(SkewMatrix<RT,3>(v)); - - std::array<Dune::FieldMatrix<RT,3,3>, 4> ddExp; - Rotation<RT,3>::DDexp(v, ddExp); - - Dune::FieldMatrix<RT,3,4> dExpInv = Rotation<RT,3>::DexpInv(q0Inv.mult(q1)); - - Dune::FieldMatrix<RT,4,4> mat(0); - for (int i=0; i<4; i++) - for (int j=0; j<4; j++) - for (int k=0; k<3; k++) - mat[i][j] += 1/intervalLength * dExp_v[i][k] * dExpInv[k][j]; - - - // ///////////////////////////////////////////////// - // The derivatives with respect to w^0 - // ///////////////////////////////////////////////// - for (int i=0; i<3; i++) { - - // \partial exp \partial w^1_j at 0 - Quaternion<RT> dw; - for (int j=0; j<4; j++) - dw[j] = 0.5*(i==j); // dExp_v_0[j][i]; - - // \xi = \exp^{-1} q_0^{-1} q_1 - Dune::FieldVector<RT,3> xi = Rotation<RT,3>::expInv(q0Inv.mult(q1)); - - Quaternion<RT> addend0; - addend0 = 0; - dExp_v.umv(xi,addend0); - addend0 = dw.mult(addend0); - addend0 /= intervalLength; - - // \parder{\xi}{w^1_j} = ... - Quaternion<RT> dwConj = dw; - dwConj.conjugate(); - //dwConj[3] -= 2 * dExp_v_0[3][i]; the last row of dExp_v_0 is zero - dwConj = dwConj.mult(q0Inv.mult(q1)); - - Dune::FieldVector<RT,3> dxi(0); - Rotation<RT,3>::DexpInv(q0Inv.mult(q1)).umv(dwConj, dxi); - - Quaternion<RT> vHv; - for (int j=0; j<4; j++) { - vHv[j] = 0; - // vHv[j] = dxi * DDexp * xi - for (int k=0; k<3; k++) - for (int l=0; l<3; l++) - vHv[j] += ddExp[j][k][l]*dxi[k]*xi[l]; - } - - vHv *= s/intervalLength/intervalLength; - - // Third addend - mat.umv(dwConj,grad[i]); - - // add up - grad[i] += addend0; - grad[i] += vHv; - - grad[i] = q0.Quaternion<double>::mult(grad[i]); - } - - - // ///////////////////////////////////////////////// - // The derivatives with respect to w^1 - // ///////////////////////////////////////////////// - for (int i=3; i<6; i++) { - - // \partial exp \partial w^1_j at 0 - Quaternion<RT> dw; - for (int j=0; j<4; j++) - dw[j] = 0.5 * ((i-3)==j); // dw[j] = dExp_v_0[j][i-3]; - - // \xi = \exp^{-1} q_0^{-1} q_1 - Dune::FieldVector<RT,3> xi = Rotation<RT,3>::expInv(q0Inv.mult(q1)); - - // \parder{\xi}{w^1_j} = ... - Dune::FieldVector<RT,3> dxi(0); - dExpInv.umv(q0Inv.Quaternion<double>::mult(q1.Quaternion<double>::mult(dw)), dxi); - - Quaternion<RT> vHv; - for (int j=0; j<4; j++) { - // vHv[j] = dxi * DDexp * xi - vHv[j] = 0; - for (int k=0; k<3; k++) - for (int l=0; l<3; l++) - vHv[j] += ddExp[j][k][l]*dxi[k]*xi[l]; - } - - vHv *= s/intervalLength/intervalLength; - - // /////////////////////////////////// - // second addend - // /////////////////////////////////// - - - dw = q0Inv.Quaternion<double>::mult(q1.Quaternion<double>::mult(dw)); - - mat.umv(dw,grad[i]); - grad[i] += vHv; - - grad[i] = q0.Quaternion<double>::mult(grad[i]); - - } - -} - -template <class GridView, class RT> -Dune::FieldVector<double, 6> RodLocalStiffness<GridView, RT>:: -getStrain(const std::vector<RigidBodyMotion<RT,3> >& localSolution, +template <class Number> +Dune::FieldVector<Number, 6> RodLocalStiffness<GridView, RT>:: +getStrain(const std::vector<RigidBodyMotion<Number,3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const { @@ -458,70 +255,58 @@ getStrain(const std::vector<RigidBodyMotion<RT,3> >& localSolution, assert(localSolution.size() == 2); - // Strain defined on each element - Dune::FieldVector<double, 6> strain(0); - // Extract local solution on this element Dune::P1LocalFiniteElement<double,double,1> localFiniteElement; - int numOfBaseFct = localFiniteElement.localCoefficients().size(); - - const Dune::FieldMatrix<double,1,1>& inv = element.geometry().jacobianInverseTransposed(pos); - - // /////////////////////////////////////// - // Compute deformation gradient - // /////////////////////////////////////// - std::vector<Dune::FieldMatrix<double,1,1> > shapeGrad; - - localFiniteElement.localBasis().evaluateJacobian(pos, shapeGrad); - for (int dof=0; dof<numOfBaseFct; dof++) { + const auto jit = element.geometry().jacobianInverseTransposed(pos); + using LocalInterpolationRule = LocalGeodesicFEFunction<1, typename GridView::ctype, + decltype(localFiniteElement), + RigidBodyMotion<Number,3> >; + LocalInterpolationRule localInterpolationRule(localFiniteElement,localSolution); - // multiply with jacobian inverse - Dune::FieldVector<double,1> tmp(0); - inv.umv(shapeGrad[dof][0], tmp); - shapeGrad[dof][0] = tmp; + auto value = localInterpolationRule.evaluate(pos); - } - - // ////////////////////////////////// - // Interpolate - // ////////////////////////////////// - - Dune::FieldVector<double,3> r_s; - for (int i=0; i<3; i++) - r_s[i] = localSolution[0].r[i]*shapeGrad[0][0] + localSolution[1].r[i]*shapeGrad[1][0]; + auto referenceDerivative = localInterpolationRule.evaluateDerivative(pos); +#if DUNE_VERSION_GTE(DUNE_COMMON, 2, 8) + auto derivative = referenceDerivative * transpose(jit); +#else + auto derivative = referenceDerivative; + derivative *= jit[0][0]; +#endif - // Interpolate the rotation at the quadrature point - Rotation<RT,3> q = Rotation<RT,3>::interpolate(localSolution[0].q, localSolution[1].q, pos); + Dune::FieldVector<Number,3> r_s = {derivative[0], derivative[1], derivative[2]}; - // Get the derivative of the rotation at the quadrature point by interpolating in $H$ - Quaternion<double> q_s = Rotation<RT,3>::interpolateDerivative(localSolution[0].q, localSolution[1].q, - pos); // Transformation from the reference element - q_s *= inv[0][0]; + Quaternion<Number> q_s(derivative[3], + derivative[4], + derivative[5], + derivative[6]); // ///////////////////////////////////////////// // Sum it all up // ///////////////////////////////////////////// + // Strain defined on each element // Part I: the shearing and stretching strain - strain[0] = r_s * q.director(0); // shear strain - strain[1] = r_s * q.director(1); // shear strain - strain[2] = r_s * q.director(2); // stretching strain + Dune::FieldVector<Number, 6> strain(0); + strain[0] = r_s * value.q.director(0); // shear strain + strain[1] = r_s * value.q.director(1); // shear strain + strain[2] = r_s * value.q.director(2); // stretching strain // Part II: the Darboux vector - Dune::FieldVector<double,3> u = darboux(q, q_s); - + Dune::FieldVector<Number,3> u = darboux(value.q, q_s); strain[3] = u[0]; strain[4] = u[1]; strain[5] = u[2]; return strain; } + template <class GridView, class RT> -Dune::FieldVector<RT, 6> RodLocalStiffness<GridView, RT>:: -getStress(const std::vector<RigidBodyMotion<RT,3> >& localSolution, +template <class Number> +Dune::FieldVector<Number, 6> RodLocalStiffness<GridView, RT>:: +getStress(const std::vector<RigidBodyMotion<Number,3> >& localSolution, const Entity& element, const Dune::FieldVector<double, 1>& pos) const { @@ -541,199 +326,6 @@ getStress(const std::vector<RigidBodyMotion<RT,3> >& localSolution, return stress; } - -template <class GridView, class RT> -void RodLocalStiffness<GridView, RT>:: -assembleGradient(const typename Basis::LocalView& localView, - const std::vector<RigidBodyMotion<RT,3> >& solution, - std::vector<Dune::FieldVector<double,6> >& gradient) const -{ - using namespace Dune; - const auto& element = localView.element(); - - std::vector<RigidBodyMotion<RT,3> > localReferenceConfiguration; - getLocalReferenceConfiguration(element, localReferenceConfiguration); - - // Extract local solution on this element - Dune::P1LocalFiniteElement<double,double,1> localFiniteElement; - int numOfBaseFct = localFiniteElement.localCoefficients().size(); - - // init - gradient.resize(numOfBaseFct); - for (size_t i=0; i<gradient.size(); i++) - gradient[i] = 0; - - double intervalLength = element.geometry().corner(1)[0] - element.geometry().corner(0)[0]; - - // /////////////////////////////////////////////////////////////////////////////////// - // Reduced integration to avoid locking: assembly is split into a shear part - // and a bending part. Different quadrature rules are used for the two parts. - // This avoids locking. - // /////////////////////////////////////////////////////////////////////////////////// - - // Get quadrature rule - const QuadratureRule<double, 1>& shearingQuad = QuadratureRules<double, 1>::rule(element.type(), shearQuadOrder); - - for (size_t pt=0; pt<shearingQuad.size(); pt++) { - - // Local position of the quadrature point - const FieldVector<double,1>& quadPos = shearingQuad[pt].position(); - - const FieldMatrix<double,1,1>& inv = element.geometry().jacobianInverseTransposed(quadPos); - const double integrationElement = element.geometry().integrationElement(quadPos); - - double weight = shearingQuad[pt].weight() * integrationElement; - - // /////////////////////////////////////// - // Compute deformation gradient - // /////////////////////////////////////// - std::vector<Dune::FieldMatrix<double,1,1> > shapeGrad; - localFiniteElement.localBasis().evaluateJacobian(quadPos, shapeGrad); - - for (int dof=0; dof<numOfBaseFct; dof++) { - - // multiply with jacobian inverse - FieldVector<double,1> tmp(0); - inv.umv(shapeGrad[dof][0], tmp); - shapeGrad[dof][0] = tmp; - - } - - // ////////////////////////////////// - // Interpolate - // ////////////////////////////////// - - FieldVector<double,3> r_s; - for (int i=0; i<3; i++) - r_s[i] = solution[0].r[i]*shapeGrad[0] + solution[1].r[i]*shapeGrad[1]; - - // Interpolate current rotation at this quadrature point - Rotation<RT,3> q = Rotation<RT,3>::interpolate(solution[0].q, solution[1].q,quadPos[0]); - - // The current strain - FieldVector<double,blocksize> strain = getStrain(solution, element, quadPos); - - // The reference strain - FieldVector<double,blocksize> referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); - - - // dd_dvij[m][i][j] = \parder {(d_k)_i} {q} - Tensor3<double,3 ,3, 4> dd_dq; - q.getFirstDerivativesOfDirectors(dd_dq); - - // First derivatives of the position - std::array<Quaternion<double>,6> dq_dwij; - interpolationDerivative(solution[0].q, solution[1].q, quadPos, dq_dwij); - - // ///////////////////////////////////////////// - // Sum it all up - // ///////////////////////////////////////////// - - for (int i=0; i<numOfBaseFct; i++) { - - // ///////////////////////////////////////////// - // The translational part - // ///////////////////////////////////////////// - - // \partial \bar{W} / \partial r^i_j - for (int j=0; j<3; j++) { - - for (int m=0; m<3; m++) - gradient[i][j] += weight - * ( A_[m] * (strain[m] - referenceStrain[m]) * shapeGrad[i] * q.director(m)[j]); - - } - - // \partial \bar{W}_v / \partial v^i_j - for (int j=0; j<3; j++) { - - for (int m=0; m<3; m++) { - FieldVector<double,3> tmp(0); - dd_dq[m].umv(dq_dwij[3*i+j], tmp); - gradient[i][3+j] += weight - * A_[m] * (strain[m] - referenceStrain[m]) * (r_s*tmp); - } - } - - } - - } - - // ///////////////////////////////////////////////////// - // Now: the bending/torsion part - // ///////////////////////////////////////////////////// - - // Get quadrature rule - const QuadratureRule<double, 1>& bendingQuad = QuadratureRules<double, 1>::rule(element.type(), bendingQuadOrder); - - for (std::size_t pt=0; pt<bendingQuad.size(); pt++) { - - // Local position of the quadrature point - const FieldVector<double,1>& quadPos = bendingQuad[pt].position(); - - const FieldMatrix<double,1,1>& inv = element.geometry().jacobianInverseTransposed(quadPos); - const double integrationElement = element.geometry().integrationElement(quadPos); - - double weight = bendingQuad[pt].weight() * integrationElement; - - // Interpolate current rotation at this quadrature point - Rotation<RT,3> q = Rotation<RT,3>::interpolate(solution[0].q, solution[1].q,quadPos[0]); - - // Get the derivative of the rotation at the quadrature point by interpolating in $H$ - Quaternion<double> q_s = Rotation<RT,3>::interpolateDerivative(solution[0].q, solution[1].q, - quadPos); - // Transformation from the reference element - q_s *= inv[0][0]; - - - // The current strain - FieldVector<double,blocksize> strain = getStrain(solution, element, quadPos); - - // The reference strain - FieldVector<double,blocksize> referenceStrain = getStrain(localReferenceConfiguration, element, quadPos); - - // First derivatives of the position - std::array<Quaternion<double>,6> dq_dwij; - interpolationDerivative(solution[0].q, solution[1].q, quadPos, dq_dwij); - - std::array<Quaternion<double>,6> dq_ds_dwij; - interpolationVelocityDerivative(solution[0].q, solution[1].q, quadPos[0]*intervalLength, intervalLength, - dq_ds_dwij); - - // ///////////////////////////////////////////// - // Sum it all up - // ///////////////////////////////////////////// - - for (int i=0; i<numOfBaseFct; i++) { - - // ///////////////////////////////////////////// - // The rotational part - // ///////////////////////////////////////////// - - // \partial \bar{W}_v / \partial v^i_j - for (int j=0; j<3; j++) { - - for (int m=0; m<3; m++) { - - // Compute derivative of the strain - /** \todo Is this formula correct? It seems strange to call - B(m) for a _derivative_ of a rotation */ - double du_dvij_m = 2 * (dq_dwij[i*3+j].B(m) * q_s) - + 2* ( q.B(m) * dq_ds_dwij[i*3+j]); - - // Sum it up - gradient[i][3+j] += weight * K_[m] - * (strain[m+3]-referenceStrain[m+3]) * du_dvij_m; - - } - - } - - } - - } -} - template <class GridView, class RT> void RodLocalStiffness<GridView, RT>:: getStrain(const std::vector<RigidBodyMotion<double,3> >& sol, diff --git a/dune/gfe/rotation.hh b/dune/gfe/rotation.hh index d7affe1ed4bb7dd7a229a61b21d5ce6465d39f7f..96ea13db09cfbd34112410fdb530091c8ede82f0 100644 --- a/dune/gfe/rotation.hh +++ b/dune/gfe/rotation.hh @@ -620,6 +620,9 @@ public: } else { + // TODO: ADOL-C does not like this part of the code, + // because arccos is not differentiable at -1 and 1. + // (Even though the overall 'difference' function is differentiable.) using std::acos; T dist = 2*acos( diff[3] ); diff --git a/src/rod3d.cc b/src/rod3d.cc index 26054037b09fa7d0ab50b6f4d762182076c08b5f..010167f53dcccaffa6f48163b6e2300490ae3581 100644 --- a/src/rod3d.cc +++ b/src/rod3d.cc @@ -1,5 +1,10 @@ #include <config.h> +// Includes for the ADOL-C automatic differentiation library +// Need to come before (almost) all others. +#include <adolc/drivers/drivers.h> +#include <dune/fufem/utilities/adolcnamespaceinjections.hh> + #include <dune/common/bitsetvector.hh> #include <dune/common/parametertree.hh> #include <dune/common/parametertreeparser.hh> @@ -14,7 +19,7 @@ #include <dune/gfe/cosseratvtkwriter.hh> #include <dune/gfe/geodesicfeassembler.hh> -#include <dune/gfe/localgeodesicfefdstiffness.hh> +#include <dune/gfe/localgeodesicfeadolcstiffness.hh> #include <dune/gfe/rigidbodymotion.hh> #include <dune/gfe/rodlocalstiffness.hh> #include <dune/gfe/rotation.hh> @@ -124,7 +129,7 @@ int main (int argc, char *argv[]) try // Create the stress-free configuration ////////////////////////////////////////////// - auto localRodEnergy = std::make_shared<RodLocalStiffness<GridView, double> >(gridView, + auto localRodEnergy = std::make_shared<RodLocalStiffness<GridView,adouble> >(gridView, A, J1, J2, E, nu); std::vector<RigidBodyMotion<double,3> > referenceConfiguration(gridView.size(1)); @@ -145,8 +150,8 @@ int main (int argc, char *argv[]) try // Create a solver for the rod problem // /////////////////////////////////////////// - LocalGeodesicFEFDStiffness<FEBasis, - TargetSpace> localStiffness(localRodEnergy.get()); + LocalGeodesicFEADOLCStiffness<FEBasis, + TargetSpace> localStiffness(localRodEnergy.get()); GeodesicFEAssembler<FEBasis,TargetSpace> rodAssembler(gridView, localStiffness);