diff --git a/dune/gfe/assemblers/localintegralenergy.hh b/dune/gfe/assemblers/localintegralenergy.hh index aa4512473bd33d045f5cfd6baa985436893f75ce..385cb10b95695fe2475764651e1de27ed9ad3957 100644 --- a/dune/gfe/assemblers/localintegralenergy.hh +++ b/dune/gfe/assemblers/localintegralenergy.hh @@ -7,13 +7,11 @@ #include <dune/geometry/quadraturerules.hh> #include <dune/gfe/assemblers/localenergy.hh> -#include <dune/gfe/cosseratstrain.hh> +#include <dune/gfe/densities/duneelasticitydensity.hh> #include <dune/gfe/densities/localdensity.hh> #include <dune/gfe/spaces/realtuple.hh> #include <dune/gfe/spaces/rotation.hh> -#include <dune/elasticity/materials/localdensity.hh> - namespace Dune::GFE { /** \brief An energy given as an integral over a density @@ -35,12 +33,6 @@ namespace Dune::GFE { public: - /** \brief Constructor with a Dune::Elasticity::LocalDensity - */ - LocalIntegralEnergy(const std::shared_ptr<Elasticity::LocalDensity<gridDim,RT,DT> >& ld) - : localDensityElasticity_(ld) - {} - /** \brief Constructor with a Dune::GFE::LocalDensity */ LocalIntegralEnergy(const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> >& ld) @@ -149,9 +141,35 @@ namespace Dune::GFE { for (size_t comp=0; comp<deformationReferenceDerivative.N(); comp++) jacobianInverseTransposed.mv(deformationReferenceDerivative[comp], deformationDerivative[comp]); + typename LocalOrientationGFEFunctionType::DerivativeType orientationDerivative; + // Integrate the energy density - if (localDensityElasticity_) - energy += weightWithintegrationElement * (*localDensityElasticity_)(x, deformationDerivative); + // We do a special-casing for DuneElasticityDensity: + // Of that one we know that it does not actually depend on the rotation. + using DEDensity = DuneElasticityDensity<FieldVector<DT,gridDim>,TargetSpace,0>; + std::shared_ptr<DEDensity> duneElasticityDensity = std::dynamic_pointer_cast<DEDensity>(localDensityGFE_); + if (duneElasticityDensity) + { + // Dummy local rotation value + ProductManifold<RealTuple<RT,gridDim>,Rotation<RT,gridDim> > value; + value[_0] = deformationValue; + value[_1] = TargetSpaceRotation::identity(); + + // Copy the two derivatives into a joint matrix object + // TODO: I am not sure about this. May the densities should get the + // separate derivatives. + FieldMatrix<RT,deformationDerivative.rows+orientationDerivative.rows, deformationDerivative.cols> derivative; + + for (int i=0; i<deformationDerivative.rows; i++) + derivative[i] = deformationDerivative[i]; + + for (int i=0; i<orientationDerivative.rows; i++) + derivative[i+deformationDerivative.rows] = 0.0; + + energy += weightWithintegrationElement * (*duneElasticityDensity)(x, + value, + derivative); + } else if (localDensityGFE_) { // The value of the local rotation Rotation<RT,gridDim> orientationValue = localOrientationGFEFunction.evaluate(quadPos); @@ -164,7 +182,6 @@ namespace Dune::GFE { typename LocalOrientationGFEFunctionType::DerivativeType orientationReferenceDerivative = localOrientationGFEFunction.evaluateDerivative(quadPos,orientationValue); // The derivative of the rotation defined on the actual element - typename LocalOrientationGFEFunctionType::DerivativeType orientationDerivative; for (size_t comp=0; comp<orientationReferenceDerivative.N(); comp++) jacobianInverseTransposed.mv(orientationReferenceDerivative[comp], orientationDerivative[comp]); @@ -190,8 +207,7 @@ namespace Dune::GFE { } protected: - const std::shared_ptr<Elasticity::LocalDensity<gridDim,RT,DT> > localDensityElasticity_ = nullptr; - const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> > localDensityGFE_ = nullptr; + const std::shared_ptr<GFE::LocalDensity<FieldVector<DT,gridDim>,TargetSpace> > localDensityGFE_; }; } // namespace Dune::GFE diff --git a/dune/gfe/densities/CMakeLists.txt b/dune/gfe/densities/CMakeLists.txt index cea45c0e9d897b47477a9d570a8062154dff5b12..4101377ac2f47cb8cdfbcd69c4f35f967f17a449 100644 --- a/dune/gfe/densities/CMakeLists.txt +++ b/dune/gfe/densities/CMakeLists.txt @@ -3,6 +3,7 @@ install(FILES bulkcosseratdensity.hh chiralskyrmiondensity.hh cosseratshelldensity.hh + duneelasticitydensity.hh harmonicdensity.hh localdensity.hh DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dune/gfe/densities) diff --git a/dune/gfe/densities/duneelasticitydensity.hh b/dune/gfe/densities/duneelasticitydensity.hh new file mode 100644 index 0000000000000000000000000000000000000000..9eb1ff98936a39eb80625aaa42cb1287bbe120b6 --- /dev/null +++ b/dune/gfe/densities/duneelasticitydensity.hh @@ -0,0 +1,65 @@ +#ifndef DUNE_GFE_DENSITIES_DUNEELASTICITYDENSITY_HH +#define DUNE_GFE_DENSITIES_DUNEELASTICITYDENSITY_HH + +#include <dune/common/fmatrix.hh> + +#include <dune/gfe/densities/localdensity.hh> + +#include <dune/elasticity/materials/localdensity.hh> + +namespace Dune::GFE +{ + + /** \brief Adapter for densities from the dune-elasticity module + * + * \tparam index The TargetSpace is typically a product with one factor being + * RealTuple. The 'index' argument selects which factor to assign the + * dune-elasticity density to. + */ + template<class Position, class TargetSpace, std::size_t index=0> + class DuneElasticityDensity final + : public LocalDensity<Position,TargetSpace> + { + using ctype = typename Position::value_type; + using field_type = typename TargetSpace::field_type; + + constexpr static auto dim = Position::size(); + constexpr static auto embeddedBlocksize = TargetSpace::EmbeddedTangentVector::dimension; + + public: + + /** \brief Constructor with a Dune::Elasticity::LocalDensity + */ + DuneElasticityDensity(const std::shared_ptr<Elasticity::LocalDensity<dim,field_type,ctype> >& elasticityDensity) + : elasticityDensity_(elasticityDensity) + {} + + /** \brief Evaluate the density + * + * \param x The current position + * \param value The deformation at the current position + * \param derivative The derivative at the current position + */ + virtual field_type operator() (const Position& x, + const TargetSpace& value, + const FieldMatrix<field_type,embeddedBlocksize,dim>& derivative) const override + { + // 'derivative' is the derivative of the entire TargetSpace point x. + // But (assuming that TargetSpace is a ProductManifold) we only want + // the parts that belongs to the factor given by the 'index' template parameter. + FieldMatrix<field_type,dim,dim> factorDerivative; + + static_assert(index==0, "index!=0 is not implemented"); + for (std::size_t i=0; i<dim; i++) + factorDerivative[i] = derivative[i]; + + return (*elasticityDensity_)(x, factorDerivative); + } + + private: + const std::shared_ptr<Elasticity::LocalDensity<dim,field_type,ctype> > elasticityDensity_; + }; + +} // namespace Dune::GFE + +#endif // DUNE_GFE_DENSITIES_DUNEELASTICITYDENSITY_HH diff --git a/src/film-on-substrate.cc b/src/film-on-substrate.cc index 97fc8ef8d204ed73bf7a83099e9be19e6980a47b..c8e0ee99878e4cf655292a2445b07b7f88b78618 100644 --- a/src/film-on-substrate.cc +++ b/src/film-on-substrate.cc @@ -62,6 +62,7 @@ #include <dune/gfe/neumannenergy.hh> #include <dune/gfe/assemblers/surfacecosseratenergy.hh> #include <dune/gfe/assemblers/sumenergy.hh> +#include <dune/gfe/densities/duneelasticitydensity.hh> #if MIXED_SPACE #include <dune/gfe/mixedriemannianpnsolver.hh> @@ -508,13 +509,17 @@ int main (int argc, char *argv[]) try using ActiveRigidBodyMotion = GFE::ProductManifold<RealTuple<adouble,dim>, Rotation<adouble,dim> >; + // Wrap dune-elasticity density as dune-gfe density + auto elasticDensityWrapped = std::make_shared<GFE::DuneElasticityDensity<FieldVector<double,dim>,ActiveRigidBodyMotion,0> >(elasticDensity); + + // Select which type of geometric interpolation to use using LocalDeformationInterpolationRule = LocalGeodesicFEFunction<dim, GridType::ctype, decltype(deformationFEBasis.localView().tree().finiteElement()), RealTuple<adouble,dim> >; using LocalOrientationInterpolationRule = LocalGeodesicFEFunction<dim, GridType::ctype, decltype(orientationFEBasis.localView().tree().finiteElement()), Rotation<adouble,dim> >; using LocalInterpolationRule = std::tuple<LocalDeformationInterpolationRule,LocalOrientationInterpolationRule>; - auto elasticEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis, LocalInterpolationRule, ActiveRigidBodyMotion> >(elasticDensity); + auto elasticEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis, LocalInterpolationRule, ActiveRigidBodyMotion> >(elasticDensityWrapped); auto neumannEnergy = std::make_shared<GFE::NeumannEnergy<CompositeBasis, RealTuple<ValueType,targetDim>, Rotation<ValueType,dim> > >(neumannBoundary,neumannFunctionPtr); auto surfaceCosseratEnergy = std::make_shared<GFE::SurfaceCosseratEnergy< decltype(stressFreeShellFunction), CompositeBasis, ActiveRigidBodyMotion> >( diff --git a/test/filmonsubstratetest.cc b/test/filmonsubstratetest.cc index c9b40dda93a72713d1e2cc7b0034606e64856fed..a79ec09818520b909909aac0da22d6fb11f0d9b3 100644 --- a/test/filmonsubstratetest.cc +++ b/test/filmonsubstratetest.cc @@ -45,6 +45,7 @@ #include <dune/gfe/neumannenergy.hh> #include <dune/gfe/assemblers/surfacecosseratenergy.hh> #include <dune/gfe/assemblers/sumenergy.hh> +#include <dune/gfe/densities/duneelasticitydensity.hh> #if MIXED_SPACE #include <dune/gfe/mixedriemannianpnsolver.hh> @@ -331,10 +332,12 @@ int main (int argc, char *argv[]) materialParameters["b2"] = "1.0"; materialParameters["b3"] = "1.0"; + using ActiveRigidBodyMotion = GFE::ProductManifold<RealTuple<adouble,dim>, Rotation<adouble,dim> >; + std::shared_ptr<Elasticity::LocalDensity<dim,ValueType> > elasticDensity; elasticDensity = std::make_shared<Elasticity::MooneyRivlinDensity<dim,ValueType> >(materialParameters); - using ActiveRigidBodyMotion = GFE::ProductManifold<RealTuple<adouble,dim>, Rotation<adouble,dim> >; + auto elasticDensityWrapped = std::make_shared<GFE::DuneElasticityDensity<FieldVector<double,dim>,ActiveRigidBodyMotion,0> >(elasticDensity); // Select which type of geometric interpolation to use using LocalDeformationInterpolationRule = LocalGeodesicFEFunction<dim, GridType::ctype, decltype(deformationFEBasis.localView().tree().finiteElement()), RealTuple<adouble,dim> >; @@ -342,7 +345,7 @@ int main (int argc, char *argv[]) using LocalInterpolationRule = std::tuple<LocalDeformationInterpolationRule,LocalOrientationInterpolationRule>; - auto elasticEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis, LocalInterpolationRule, ActiveRigidBodyMotion> >(elasticDensity); + auto elasticEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis, LocalInterpolationRule, ActiveRigidBodyMotion> >(elasticDensityWrapped); auto neumannEnergy = std::make_shared<GFE::NeumannEnergy<CompositeBasis, RealTuple<ValueType,targetDim>, Rotation<ValueType,dim> > >(neumannBoundary,neumannFunction); auto surfaceCosseratEnergy = std::make_shared<GFE::SurfaceCosseratEnergy<