From bed3da256928852b46f46d39694e5713e3831c82 Mon Sep 17 00:00:00 2001 From: Oliver Sander <oliver.sander@tu-dresden.de> Date: Sun, 8 Nov 2020 21:11:04 +0100 Subject: [PATCH] Move all rod stress and strain methods to local energy implementation As a first step towards getting rid of the RodAssembler class, this patch moves the getStrain, getStress, and getResultantForce methods to the RodLocalStiffness class. I am not 100% convinced that that is the best place for them, but I can't think of a better one right now. --- dune/gfe/rodassembler.cc | 161 ----------------------------- dune/gfe/rodassembler.hh | 12 --- dune/gfe/rodlocalstiffness.hh | 187 +++++++++++++++++++++++++++++++--- 3 files changed, 175 insertions(+), 185 deletions(-) diff --git a/dune/gfe/rodassembler.cc b/dune/gfe/rodassembler.cc index 32300bd3..01b5e2d7 100644 --- a/dune/gfe/rodassembler.cc +++ b/dune/gfe/rodassembler.cc @@ -57,167 +57,6 @@ assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol, } -template <class GridView> -void RodAssembler<GridView,3>:: -getStrain(const std::vector<RigidBodyMotion<double,3> >& sol, - Dune::BlockVector<Dune::FieldVector<double, blocksize> >& strain) const -{ - using namespace Dune; - - const typename GridView::Traits::IndexSet& indexSet = this->basis_.gridView().indexSet(); - - if (sol.size()!=this->basis_.size()) - DUNE_THROW(Exception, "Solution vector doesn't match the grid!"); - - // Strain defined on each element - strain.resize(indexSet.size(0)); - strain = 0; - - // Loop over all elements - for (const auto& element : elements(this->basis_.gridView())) - { - int elementIdx = indexSet.index(element); - - // Extract local solution on this element - Dune::P1LocalFiniteElement<double,double,gridDim> localFiniteElement; - int numOfBaseFct = localFiniteElement.localCoefficients().size(); - - std::vector<RigidBodyMotion<double,3> > localSolution(2); - - for (int i=0; i<numOfBaseFct; i++) - localSolution[i] = sol[indexSet.subIndex(element,i,gridDim)]; - - // Get quadrature rule - const int polOrd = 2; - const auto& quad = QuadratureRules<double, gridDim>::rule(element.type(), polOrd); - - for (std::size_t pt=0; pt<quad.size(); pt++) { - - // Local position of the quadrature point - const FieldVector<double,gridDim>& quadPos = quad[pt].position(); - - double weight = quad[pt].weight() * element.geometry().integrationElement(quadPos); - - FieldVector<double,blocksize> localStrain = std::dynamic_pointer_cast<RodLocalStiffness<GridView, double> >(this->localStiffness_)->getStrain(localSolution, element, quad[pt].position()); - - // Sum it all up - strain[elementIdx].axpy(weight, localStrain); - - } - - // ///////////////////////////////////////////////////////////////////////// - // We want the average strain per element. Therefore we have to divide - // the integral we just computed by the element volume. - // ///////////////////////////////////////////////////////////////////////// - // we know the element is a line, therefore the integration element is the volume - FieldVector<double,1> dummyPos(0.5); - strain[elementIdx] /= element.geometry().integrationElement(dummyPos); - - } - -} - -template <class GridView> -void RodAssembler<GridView,3>:: -getStress(const std::vector<RigidBodyMotion<double,3> >& sol, - Dune::BlockVector<Dune::FieldVector<double, blocksize> >& stress) const -{ - // Get the strain - getStrain(sol,stress); - - // Get reference strain - Dune::BlockVector<Dune::FieldVector<double, blocksize> > referenceStrain; - getStrain(dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_, referenceStrain); - - // Linear diagonal constitutive law - for (size_t i=0; i<stress.size(); i++) { - for (int j=0; j<3; j++) { - stress[i][j] = (stress[i][j] - referenceStrain[i][j]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->A_[j]; - stress[i][j+3] = (stress[i][j+3] - referenceStrain[i][j+3]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->K_[j]; - } - } -} - -template <class GridView> -template <class PatchGridView> -Dune::FieldVector<double,6> RodAssembler<GridView,3>:: -getResultantForce(const BoundaryPatch<PatchGridView>& boundary, - const std::vector<RigidBodyMotion<double,3> >& sol) const -{ - using namespace Dune; - - // if (gridView_ != &boundary.gridView()) - // DUNE_THROW(Dune::Exception, "The boundary patch has to match the grid view of the assembler!"); - - const typename GridView::Traits::IndexSet& indexSet = this->basis_.gridView().indexSet(); - - if (sol.size()!=indexSet.size(gridDim)) - DUNE_THROW(Exception, "Solution vector doesn't match the grid!"); - - FieldVector<double,3> canonicalStress(0); - FieldVector<double,3> canonicalTorque(0); - - // Loop over the given boundary - typename BoundaryPatch<PatchGridView>::iterator it = boundary.begin(); - typename BoundaryPatch<PatchGridView>::iterator endIt = boundary.end(); - - for (; it!=endIt; ++it) { - - // ////////////////////////////////////////////// - // Compute force across this boundary face - // ////////////////////////////////////////////// - - double pos = it->geometryInInside().corner(0); - - std::vector<RigidBodyMotion<double,3> > localSolution(2); - localSolution[0] = sol[indexSet.subIndex(*it->inside(),0,1)]; - localSolution[1] = sol[indexSet.subIndex(*it->inside(),1,1)]; - - std::vector<RigidBodyMotion<double,3> > localRefConf(2); - localRefConf[0] = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_[indexSet.subIndex(*it->inside(),0,1)]; - localRefConf[1] = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_[indexSet.subIndex(*it->inside(),1,1)]; - - FieldVector<double, blocksize> strain = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->getStrain(localSolution, *it->inside(), pos); - FieldVector<double, blocksize> referenceStrain = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->getStrain(localRefConf, *it->inside(), pos); - - FieldVector<double,3> localStress; - for (int i=0; i<3; i++) - localStress[i] = (strain[i] - referenceStrain[i]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->A_[i]; - - FieldVector<double,3> localTorque; - for (int i=0; i<3; i++) - localTorque[i] = (strain[i+3] - referenceStrain[i+3]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->K_[i]; - - // Transform stress given with respect to the basis given by the three directors to - // the canonical basis of R^3 - - FieldMatrix<double,3,3> orientationMatrix; - sol[indexSet.subIndex(*it->inside(),it->indexInInside(),1)].q.matrix(orientationMatrix); - - orientationMatrix.umv(localStress, canonicalStress); - - orientationMatrix.umv(localTorque, canonicalTorque); - // Reverse transformation to make sure we did the correct thing -// assert( std::abs(localStress[0]-canonicalStress*sol[0].q.director(0)) < 1e-6 ); -// assert( std::abs(localStress[1]-canonicalStress*sol[0].q.director(1)) < 1e-6 ); -// assert( std::abs(localStress[2]-canonicalStress*sol[0].q.director(2)) < 1e-6 ); - - // Multiply force times boundary normal to get the transmitted force - canonicalStress *= it->unitOuterNormal(FieldVector<double,0>(0))[0]; - canonicalTorque *= it->unitOuterNormal(FieldVector<double,0>(0))[0]; - - } - - Dune::FieldVector<double,6> result; - for (int i=0; i<3; i++) { - result[i] = canonicalStress[i]; - result[i+3] = canonicalTorque[i]; - } - - return result; -} - - template <class GridView> void RodAssembler<GridView,2>:: assembleMatrix(const std::vector<RigidBodyMotion<double,2> >& sol, diff --git a/dune/gfe/rodassembler.hh b/dune/gfe/rodassembler.hh index 64c1327e..70ab003e 100644 --- a/dune/gfe/rodassembler.hh +++ b/dune/gfe/rodassembler.hh @@ -74,18 +74,6 @@ public: virtual void assembleGradient(const std::vector<RigidBodyMotion<double,3> >& sol, Dune::BlockVector<Dune::FieldVector<double, blocksize> >& grad) const override; - void getStrain(const std::vector<RigidBodyMotion<double,3> >& sol, - Dune::BlockVector<Dune::FieldVector<double, blocksize> >& strain) const; - - void getStress(const std::vector<RigidBodyMotion<double,3> >& sol, - Dune::BlockVector<Dune::FieldVector<double, blocksize> >& stress) const; - - /** \brief Return resultant force across boundary in canonical coordinates - - \note Linear run-time in the size of the grid */ - template <class PatchGridView> - Dune::FieldVector<double,6> getResultantForce(const BoundaryPatch<PatchGridView>& boundary, - const std::vector<RigidBodyMotion<double,3> >& sol) const; }; // end class diff --git a/dune/gfe/rodlocalstiffness.hh b/dune/gfe/rodlocalstiffness.hh index 5157a30e..f5a8b673 100644 --- a/dune/gfe/rodlocalstiffness.hh +++ b/dune/gfe/rodlocalstiffness.hh @@ -9,6 +9,8 @@ #include <dune/functions/functionspacebases/lagrangebasis.hh> +#include <dune/fufem/boundarypatch.hh> + #include <dune/gfe/localfirstordermodel.hh> #include "rigidbodymotion.hh" @@ -105,14 +107,31 @@ public: 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, 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, const Entity& element, const Dune::FieldVector<double,1>& pos) const; + /** \brief Get average strain for each element */ + void getStrain(const std::vector<RigidBodyMotion<double,3> >& sol, + Dune::BlockVector<Dune::FieldVector<double, blocksize> >& strain) const; + + /** \brief Get average stress for each element */ + void getStress(const std::vector<RigidBodyMotion<double,3> >& sol, + Dune::BlockVector<Dune::FieldVector<double, blocksize> >& stress) const; + + /** \brief Return resultant force across boundary in canonical coordinates + + \note Linear run-time in the size of the grid */ + template <class PatchGridView> + Dune::FieldVector<double,6> getResultantForce(const BoundaryPatch<PatchGridView>& boundary, + const std::vector<RigidBodyMotion<double,3> >& sol) const; + protected: void getLocalReferenceConfiguration(const Entity& element, @@ -147,8 +166,8 @@ protected: }; -template <class GridType, class RT> -RT RodLocalStiffness<GridType, RT>:: +template <class GridView, class RT> +RT RodLocalStiffness<GridView, RT>:: energy(const typename Basis::LocalView& localView, const std::vector<RigidBodyMotion<RT,3> >& localSolution) const { @@ -217,8 +236,8 @@ energy(const typename Basis::LocalView& localView, } -template <class GridType, class RT> -void RodLocalStiffness<GridType, RT>:: +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) { @@ -302,8 +321,8 @@ interpolationDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& q1, doub -template <class GridType, class RT> -void RodLocalStiffness<GridType, RT>:: +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) { @@ -428,8 +447,8 @@ interpolationVelocityDerivative(const Rotation<RT,3>& q0, const Rotation<RT,3>& } -template <class GridType, class RT> -Dune::FieldVector<double, 6> RodLocalStiffness<GridType, RT>:: +template <class GridView, class RT> +Dune::FieldVector<double, 6> RodLocalStiffness<GridView, RT>:: getStrain(const std::vector<RigidBodyMotion<RT,3> >& localSolution, const Entity& element, const Dune::FieldVector<double,1>& pos) const @@ -500,8 +519,8 @@ getStrain(const std::vector<RigidBodyMotion<RT,3> >& localSolution, return strain; } -template <class GridType, class RT> -Dune::FieldVector<RT, 6> RodLocalStiffness<GridType, RT>:: +template <class GridView, class RT> +Dune::FieldVector<RT, 6> RodLocalStiffness<GridView, RT>:: getStress(const std::vector<RigidBodyMotion<RT,3> >& localSolution, const Entity& element, const Dune::FieldVector<double, 1>& pos) const @@ -523,8 +542,8 @@ getStress(const std::vector<RigidBodyMotion<RT,3> >& localSolution, } -template <class GridType, class RT> -void RodLocalStiffness<GridType, RT>:: +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 @@ -715,6 +734,150 @@ assembleGradient(const typename Basis::LocalView& localView, } } +template <class GridView, class RT> +void RodLocalStiffness<GridView, RT>:: +getStrain(const std::vector<RigidBodyMotion<double,3> >& sol, + Dune::BlockVector<Dune::FieldVector<double, blocksize> >& strain) const +{ + const typename GridView::Traits::IndexSet& indexSet = this->basis_.gridView().indexSet(); + + if (sol.size()!=this->basis_.size()) + DUNE_THROW(Dune::Exception, "Solution vector doesn't match the grid!"); + + // Strain defined on each element + strain.resize(indexSet.size(0)); + strain = 0; + + // Loop over all elements + for (const auto& element : elements(this->basis_.gridView())) + { + int elementIdx = indexSet.index(element); + + // Extract local solution on this element + Dune::P1LocalFiniteElement<double,double,1> localFiniteElement; + int numOfBaseFct = localFiniteElement.localCoefficients().size(); + + std::vector<RigidBodyMotion<double,3> > localSolution(2); + + for (int i=0; i<numOfBaseFct; i++) + localSolution[i] = sol[indexSet.subIndex(element,i,1)]; + + // Get quadrature rule + const int polOrd = 2; + const auto& quad = Dune::QuadratureRules<double, 1>::rule(element.type(), polOrd); + + for (std::size_t pt=0; pt<quad.size(); pt++) + { + // Local position of the quadrature point + const auto quadPos = quad[pt].position(); + + double weight = quad[pt].weight() * element.geometry().integrationElement(quadPos); + + auto localStrain = std::dynamic_pointer_cast<RodLocalStiffness<GridView, double> >(this->localStiffness_)->getStrain(localSolution, element, quad[pt].position()); + + // Sum it all up + strain[elementIdx].axpy(weight, localStrain); + } + + // ///////////////////////////////////////////////////////////////////////// + // We want the average strain per element. Therefore we have to divide + // the integral we just computed by the element volume. + // ///////////////////////////////////////////////////////////////////////// + // we know the element is a line, therefore the integration element is the volume + Dune::FieldVector<double,1> dummyPos(0.5); + strain[elementIdx] /= element.geometry().integrationElement(dummyPos); + } +} + +template <class GridView, class RT> +void RodLocalStiffness<GridView, RT>:: +getStress(const std::vector<RigidBodyMotion<double,3> >& sol, + Dune::BlockVector<Dune::FieldVector<double, blocksize> >& stress) const +{ + // Get the strain + getStrain(sol,stress); + + // Get reference strain + Dune::BlockVector<Dune::FieldVector<double, blocksize> > referenceStrain; + getStrain(dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_, referenceStrain); + + // Linear diagonal constitutive law + for (size_t i=0; i<stress.size(); i++) + { + for (int j=0; j<3; j++) + { + stress[i][j] = (stress[i][j] - referenceStrain[i][j]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->A_[j]; + stress[i][j+3] = (stress[i][j+3] - referenceStrain[i][j+3]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->K_[j]; + } + } +} + +template <class GridView, class RT> +template <class PatchGridView> +Dune::FieldVector<double,6> RodLocalStiffness<GridView, RT>:: +getResultantForce(const BoundaryPatch<PatchGridView>& boundary, + const std::vector<RigidBodyMotion<double,3> >& sol) const +{ + const typename GridView::Traits::IndexSet& indexSet = this->basis_.gridView().indexSet(); + + if (sol.size()!=indexSet.size(1)) + DUNE_THROW(Dune::Exception, "Solution vector doesn't match the grid!"); + + Dune::FieldVector<double,3> canonicalStress(0); + Dune::FieldVector<double,3> canonicalTorque(0); + + // Loop over the given boundary + for (auto facet : boundary) + { + // ////////////////////////////////////////////// + // Compute force across this boundary face + // ////////////////////////////////////////////// + + double pos = facet.geometryInInside().corner(0); + + std::vector<RigidBodyMotion<double,3> > localSolution(2); + localSolution[0] = sol[indexSet.subIndex(*facet.inside(),0,1)]; + localSolution[1] = sol[indexSet.subIndex(*facet.inside(),1,1)]; + + std::vector<RigidBodyMotion<double,3> > localRefConf(2); + localRefConf[0] = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_[indexSet.subIndex(*facet.inside(),0,1)]; + localRefConf[1] = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->referenceConfiguration_[indexSet.subIndex(*facet.inside(),1,1)]; + + auto strain = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->getStrain(localSolution, *facet.inside(), pos); + auto referenceStrain = dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->getStrain(localRefConf, *facet.inside(), pos); + + Dune::FieldVector<double,3> localStress; + for (int i=0; i<3; i++) + localStress[i] = (strain[i] - referenceStrain[i]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->A_[i]; + + Dune::FieldVector<double,3> localTorque; + for (int i=0; i<3; i++) + localTorque[i] = (strain[i+3] - referenceStrain[i+3]) * dynamic_cast<RodLocalStiffness<GridView, double>* >(this->localStiffness_)->K_[i]; + + // Transform stress given with respect to the basis given by the three directors to + // the canonical basis of R^3 + + Dune::FieldMatrix<double,3,3> orientationMatrix; + sol[indexSet.subIndex(*facet.inside(),facet.indexInInside(),1)].q.matrix(orientationMatrix); + + orientationMatrix.umv(localStress, canonicalStress); + + orientationMatrix.umv(localTorque, canonicalTorque); + + // Multiply force times boundary normal to get the transmitted force + canonicalStress *= facet.unitOuterNormal(Dune::FieldVector<double,0>(0))[0]; + canonicalTorque *= facet.unitOuterNormal(Dune::FieldVector<double,0>(0))[0]; + } + + Dune::FieldVector<double,6> result; + for (int i=0; i<3; i++) + { + result[i] = canonicalStress[i]; + result[i+3] = canonicalTorque[i]; + } + + return result; +} #endif -- GitLab