diff --git a/CHANGELOG.md b/CHANGELOG.md index ccc354c82fb15ad0b4b2a2f6f74c07a5138882bc..f452d9055c0fd7990f1adf7c8824f81c6d5ba3b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ - The class `LocalIntegralEnergy` now does not construct the local interpolation rule itself anymore. Rather, it expects to be given one in its constructor. This will allow interpolation rules with state. + +- The same holds for `CosseratRodEnergy`. Unfortunately, that move + implies that `CosseratRodEnergy` gains an extra template argument + which specifies the GFE function used to implement the reference + configuration. - The classes `LocalGeodesicFEFunction` and `LocalProjectedFEFunction` now take a `dune-functions` basis as their first arguments, instead diff --git a/dune/gfe/assemblers/cosseratrodenergy.hh b/dune/gfe/assemblers/cosseratrodenergy.hh index d8dde8cd048f7246a1a0f9900f3228ece1d0d08d..d47fa74a9ec5ed5cc6d042dbb6159e6468f30362 100644 --- a/dune/gfe/assemblers/cosseratrodenergy.hh +++ b/dune/gfe/assemblers/cosseratrodenergy.hh @@ -2,6 +2,7 @@ #define DUNE_GFE_COSSERATRODENERGY_HH #include <array> +#include <memory> #include <dune/common/fmatrix.hh> #include <dune/common/version.hh> @@ -21,7 +22,7 @@ namespace Dune::GFE { - template<class Basis, class LocalInterpolationRule, class RT> + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> class CosseratRodEnergy : public LocalEnergy<Basis, ProductManifold<RealTuple<RT,3>,Rotation<RT,3> > > { @@ -43,6 +44,14 @@ namespace Dune::GFE public: + /** \brief The current configuration whose energy is being computed + */ + const std::shared_ptr<LocalInterpolationRule> localGFEFunction_; + + /** \brief The GFE function that implements the stress-free reference configuration + */ + const std::shared_ptr<ReferenceInterpolationRule> localReferenceConfiguration_; + /** \brief The stress-free configuration The number type cannot be RT, because RT become `adouble` when @@ -68,22 +77,68 @@ namespace Dune::GFE GridView gridView_; //! Constructor - CosseratRodEnergy(const GridView& gridView, + CosseratRodEnergy(std::shared_ptr<LocalInterpolationRule> localGFEFunction, + std::shared_ptr<ReferenceInterpolationRule> localReferenceConfiguration, + const GridView& gridView, const std::array<double,3>& K, const std::array<double,3>& A) - : K_(K), + : localGFEFunction_(localGFEFunction) + , localReferenceConfiguration_(localReferenceConfiguration) + , K_(K), A_(A), gridView_(gridView) {} + //! Constructor + CosseratRodEnergy(LocalInterpolationRule&& localGFEFunction, + ReferenceInterpolationRule&& localReferenceConfiguration, + const GridView& gridView, + const std::array<double,3>& K, const std::array<double,3>& A) + : localGFEFunction_(std::make_shared<LocalInterpolationRule>(std::move(localGFEFunction))) + , localReferenceConfiguration_(std::make_shared<ReferenceInterpolationRule>(std::move(localReferenceConfiguration))) + , K_(K), + A_(A), + gridView_(gridView) + {} + + /** \brief Constructor setting shape constants and material parameters + \param A The rod section area + \param J1, J2 The geometric moments (Flächenträgheitsmomente) + \param E Young's modulus + \param nu Poisson number + */ + CosseratRodEnergy(std::shared_ptr<LocalInterpolationRule> localGFEFunction, + std::shared_ptr<ReferenceInterpolationRule> localReferenceConfiguration, + const GridView& gridView, + double A, double J1, double J2, double E, double nu) + : localGFEFunction_(localGFEFunction) + , localReferenceConfiguration_(localReferenceConfiguration) + , gridView_(gridView) + { + // shear modulus + double G = E/(2+2*nu); + + K_[0] = E * J1; + K_[1] = E * J2; + K_[2] = G * (J1 + J2); + + A_[0] = G * A; + A_[1] = G * A; + A_[2] = E * A; + } + /** \brief Constructor setting shape constants and material parameters \param A The rod section area \param J1, J2 The geometric moments (Flächenträgheitsmomente) \param E Young's modulus \param nu Poisson number */ - CosseratRodEnergy(const GridView& gridView, + CosseratRodEnergy(LocalInterpolationRule&& localGFEFunction, + ReferenceInterpolationRule&& localReferenceConfiguration, + const GridView& gridView, double A, double J1, double J2, double E, double nu) - : gridView_(gridView) + : localGFEFunction_(std::make_shared<LocalInterpolationRule>(std::move(localGFEFunction))) + , localReferenceConfiguration_(std::make_shared<ReferenceInterpolationRule>(std::move(localReferenceConfiguration))) + , gridView_(gridView) { // shear modulus double G = E/(2+2*nu); @@ -173,23 +228,20 @@ namespace Dune::GFE }; - template<class Basis, class LocalInterpolationRule, class RT> - RT CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> + RT CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: energy(const typename Basis::LocalView& localView, const std::vector<TargetSpace>& localCoefficients) const { const auto& localFiniteElement = localView.tree().finiteElement(); - LocalInterpolationRule localConfiguration; - localConfiguration.bind(localFiniteElement, localCoefficients); + localGFEFunction_->bind(localFiniteElement, localCoefficients); const auto& element = localView.element(); RT energy = 0; std::vector<ProductManifold<RealTuple<double,3>,Rotation<double,3> > > localReferenceCoefficients = getLocalReferenceConfiguration(localView); - using InactiveLocalInterpolationRule = typename LocalInterpolationRule::template rebind<ProductManifold<RealTuple<double,3>,Rotation<double,3> > >::other; - InactiveLocalInterpolationRule localReferenceConfiguration; - localReferenceConfiguration.bind(localFiniteElement, localReferenceCoefficients); + localReferenceConfiguration_->bind(localFiniteElement, localReferenceCoefficients); // /////////////////////////////////////////////////////////////////////////////// // The following two loops are a reduced integration scheme. We integrate @@ -208,10 +260,10 @@ namespace Dune::GFE double weight = shearingQuad[pt].weight() * integrationElement; - auto strain = getStrain(localConfiguration, element, quadPos); + auto strain = getStrain(*localGFEFunction_, element, quadPos); // The reference strain - auto 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]); @@ -228,10 +280,10 @@ namespace Dune::GFE double weight = bendingQuad[pt].weight() * element.geometry().integrationElement(quadPos); - auto strain = getStrain(localConfiguration, element, quadPos); + auto strain = getStrain(*localGFEFunction_, element, quadPos); // The reference strain - auto 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++) @@ -243,9 +295,9 @@ namespace Dune::GFE } - template<class Basis, class LocalInterpolationRule, class RT> + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> template <class ReboundLocalInterpolationRule> - auto CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + auto CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: getStrain(const ReboundLocalInterpolationRule& localInterpolation, const Entity& element, const FieldVector<double,1>& pos) const @@ -288,9 +340,9 @@ namespace Dune::GFE return strain; } - template<class Basis, class LocalInterpolationRule, class RT> + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> template <class Number> - auto CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + auto CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: getStress(const std::vector<ProductManifold<RealTuple<Number,3>,Rotation<Number,3> > >& localSolution, const Entity& element, const FieldVector<double, 1>& pos) const @@ -311,8 +363,8 @@ namespace Dune::GFE return stress; } - template<class Basis, class LocalInterpolationRule, class RT> - void CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> + void CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: getStrain(const std::vector<ProductManifold<RealTuple<double,3>,Rotation<double,3> > >& sol, BlockVector<FieldVector<double, blocksize> >& strain) const { @@ -366,8 +418,8 @@ namespace Dune::GFE } } - template<class Basis, class LocalInterpolationRule, class RT> - void CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> + void CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: getStress(const std::vector<ProductManifold<RealTuple<double,3>,Rotation<double,3> > >& sol, BlockVector<FieldVector<double, blocksize> >& stress) const { @@ -389,9 +441,9 @@ namespace Dune::GFE } } - template<class Basis, class LocalInterpolationRule, class RT> + template<class Basis, class LocalInterpolationRule, class ReferenceInterpolationRule, class RT> template <class PatchGridView> - auto CosseratRodEnergy<Basis, LocalInterpolationRule, RT>:: + auto CosseratRodEnergy<Basis, LocalInterpolationRule, ReferenceInterpolationRule, RT>:: getResultantForce(const BoundaryPatch<PatchGridView>& boundary, const std::vector<ProductManifold<RealTuple<double,3>,Rotation<double,3> > >& sol) const { diff --git a/src/cosserat-rod.cc b/src/cosserat-rod.cc index 3df2a0ccc2c2bf1e9e539d2347fe983086dc56ff..646dc9427ed9506aa082705283a6b754922e5100 100644 --- a/src/cosserat-rod.cc +++ b/src/cosserat-rod.cc @@ -219,24 +219,36 @@ int main (int argc, char *argv[]) try // Create the energy and assembler ////////////////////////////////////////////// + // GFE function describing the reference configuration + using ReferenceGeodesicInterpolationRule = GFE::LocalGeodesicFEFunction<ScalarBasis, TargetSpace>; + using ReferenceProjectedInterpolationRule = GFE::LocalProjectedFEFunction<ScalarBasis, TargetSpace>; + ReferenceGeodesicInterpolationRule referenceGeodesicFEFunction; + ReferenceProjectedInterpolationRule referenceProjectedFEFunction; + using ATargetSpace = TargetSpace::rebind<adouble>::other; using GeodesicInterpolationRule = GFE::LocalGeodesicFEFunction<ScalarBasis, ATargetSpace>; using ProjectedInterpolationRule = GFE::LocalProjectedFEFunction<ScalarBasis, ATargetSpace>; + GeodesicInterpolationRule localGeodesicFEFunction; + ProjectedInterpolationRule localProjectedFEFunction; // Assembler using ADOL-C std::shared_ptr<GFE::LocalEnergy<ScalarBasis,ATargetSpace> > localRodEnergy; if (parameterSet["interpolationMethod"] == "geodesic") { - auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, GeodesicInterpolationRule, adouble> >(gridView, - A, J1, J2, E, nu); + auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, GeodesicInterpolationRule, ReferenceGeodesicInterpolationRule, adouble> >(std::move(localGeodesicFEFunction), + std::move(referenceGeodesicFEFunction), + gridView, + A, J1, J2, E, nu); energy->setReferenceConfiguration(referenceConfiguration); localRodEnergy = energy; } else if (parameterSet["interpolationMethod"] == "projected") { - auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, ProjectedInterpolationRule, adouble> >(gridView, - A, J1, J2, E, nu); + auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, ProjectedInterpolationRule, ReferenceProjectedInterpolationRule, adouble> >(std::move(localProjectedFEFunction), + std::move(referenceProjectedFEFunction), + gridView, + A, J1, J2, E, nu); energy->setReferenceConfiguration(referenceConfiguration); localRodEnergy = energy; } diff --git a/test/cosseratrodenergytest.cc b/test/cosseratrodenergytest.cc index 72f08f5f9e2ed6fda12f75e59189b267085e4df6..0ef37b2aed8875a28246f6010a7d117b793ea2ad 100644 --- a/test/cosseratrodenergytest.cc +++ b/test/cosseratrodenergytest.cc @@ -73,10 +73,15 @@ int main (int argc, char *argv[]) try using GeodesicInterpolationRule = GFE::LocalGeodesicFEFunction<FEBasis, TargetSpace>; + GeodesicInterpolationRule localGFEFunction; + GeodesicInterpolationRule referenceGFEFunction; GFE::CosseratRodEnergy<FEBasis, GeodesicInterpolationRule, - double> localRodEnergy(gridView, + GeodesicInterpolationRule, + double> localRodEnergy(std::move(localGFEFunction), + std::move(referenceGFEFunction), + gridView, 1,1,1,1e6,0.3); SolutionType referenceConfiguration(gridView.size(1)); diff --git a/test/cosseratrodtest.cc b/test/cosseratrodtest.cc index 51b42cd5ccc97273e438b8ae77c6fad7c6087cb5..630b8e536fb0fc1400eef24dd478c72c86fc1a36 100644 --- a/test/cosseratrodtest.cc +++ b/test/cosseratrodtest.cc @@ -134,6 +134,13 @@ int main (int argc, char *argv[]) try using ATargetSpace = TargetSpace::rebind<adouble>::other; using GeodesicInterpolationRule = GFE::LocalGeodesicFEFunction<ScalarBasis, ATargetSpace>; using ProjectedInterpolationRule = GFE::LocalProjectedFEFunction<ScalarBasis, ATargetSpace>; + GeodesicInterpolationRule localGeodesicFEFunction; + ProjectedInterpolationRule localProjectedFEFunction; + + using ReferenceGeodesicInterpolationRule = GFE::LocalGeodesicFEFunction<ScalarBasis, TargetSpace>; + using ReferenceProjectedInterpolationRule = GFE::LocalProjectedFEFunction<ScalarBasis, TargetSpace>; + ReferenceGeodesicInterpolationRule localReferenceGeodesicFEFunction; + ReferenceProjectedInterpolationRule localReferenceProjectedFEFunction; // Assembler using ADOL-C std::shared_ptr<GFE::LocalEnergy<ScalarBasis,ATargetSpace> > localRodEnergy; @@ -142,15 +149,17 @@ int main (int argc, char *argv[]) try if (interpolationMethod == "geodesic") { - auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, GeodesicInterpolationRule, adouble> >(gridView, - A, J1, J2, E, nu); + auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, GeodesicInterpolationRule, ReferenceGeodesicInterpolationRule, adouble> >(std::move(localGeodesicFEFunction), + std::move(localReferenceGeodesicFEFunction), gridView, + A, J1, J2, E, nu); energy->setReferenceConfiguration(referenceConfiguration); localRodEnergy = energy; } else if (interpolationMethod == "projected") { - auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, ProjectedInterpolationRule, adouble> >(gridView, - A, J1, J2, E, nu); + auto energy = std::make_shared<GFE::CosseratRodEnergy<ScalarBasis, ProjectedInterpolationRule, ReferenceProjectedInterpolationRule, adouble> >(std::move(localProjectedFEFunction), + std::move(localReferenceProjectedFEFunction), gridView, + A, J1, J2, E, nu); energy->setReferenceConfiguration(referenceConfiguration); localRodEnergy = energy; }