diff --git a/src/cosserat-continuum.cc b/src/cosserat-continuum.cc index fd06f9edd062446e3aeb6879b925b97d4194c2e5..f6eafed572b34e009cc16317dc5039989e423766 100644 --- a/src/cosserat-continuum.cc +++ b/src/cosserat-continuum.cc @@ -70,6 +70,7 @@ #include <dune/gfe/assemblers/sumenergy.hh> #include <dune/gfe/densities/bulkcosseratdensity.hh> #include <dune/gfe/densities/cosseratvolumeloaddensity.hh> +#include <dune/gfe/densities/cosseratshelldensity.hh> #include <dune/gfe/densities/planarcosseratshelldensity.hh> #if MIXED_SPACE @@ -108,19 +109,39 @@ static_assert(displacementOrder==rotationOrder, "displacement and rotation order // Image space of the geodesic fe functions using TargetSpace = GFE::ProductManifold<RealTuple<double,3>,Rotation<double,3> >; -// Method to construct a density that matches the grid dimension. +// Method to construct a Cosserat energy that matches the grid dimension. // This cannot be done inside the 'main' method, because 'constexpr if' only works // when its argument depends on a template parameter. -template <typename LocalCoordinate> -auto createDensity(const ParameterTree& materialParameters) +// +// TODO: Do we really need the 'creator' argument? +template <typename Basis, typename InterpolationRule, typename TargetSpace, typename Creator> +auto createCosseratEnergy(const ParameterTree& materialParameters, + const Creator creator) { - if constexpr (LocalCoordinate::size()==2) + using GridView = typename Basis::GridView; + constexpr auto dim = GridView::dimension; + constexpr auto dimworld = GridView::dimensionworld; + + using LocalCoordinate = typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate; + + if constexpr (dim==2 && dimworld==2) { - return std::make_shared<GFE::PlanarCosseratShellDensity<LocalCoordinate, adouble> >(materialParameters); + auto density = std::make_shared<GFE::PlanarCosseratShellDensity<LocalCoordinate, adouble> >(materialParameters); + + return std::make_shared<GFE::LocalIntegralEnergy<Basis,InterpolationRule,TargetSpace> >(density); + } + else if constexpr (LocalCoordinate::size()==2 && dimworld==3) + { + using GlobalCoordinate = typename GridView::template Codim<0>::Entity::Geometry::GlobalCoordinate; + auto density = std::make_shared<GFE::CosseratShellDensity<GlobalCoordinate, adouble> >(materialParameters); + + return std::make_shared<NonplanarCosseratShellEnergy<Basis, 3, adouble, decltype(creator)> >(materialParameters, &creator); } else { - return std::make_shared<GFE::BulkCosseratDensity<LocalCoordinate, adouble> >(materialParameters); + auto density = std::make_shared<GFE::BulkCosseratDensity<LocalCoordinate, adouble> >(materialParameters); + + return std::make_shared<GFE::LocalIntegralEnergy<Basis,InterpolationRule,TargetSpace> >(density); } } @@ -564,24 +585,11 @@ int main (int argc, char *argv[]) try // The energy on one element auto sumEnergy = std::make_shared<GFE::SumEnergy<CompositeBasis, RealTuple<adouble,3>,Rotation<adouble,3> > >(); - if (dim==dimworld) { - auto cosseratDensity = createDensity<LocalCoordinate>(materialParameters); + // The actual Cosserat energy + auto localCosseratEnergy = createCosseratEnergy<CompositeBasis,AInterpolationRule,ATargetSpace,decltype(creator)>(materialParameters, + creator); - auto localCosseratEnergy = std::make_shared<GFE::LocalIntegralEnergy<CompositeBasis,AInterpolationRule,ATargetSpace> >(cosseratDensity); - - sumEnergy->addLocalEnergy(localCosseratEnergy); - } - else - { - static_assert((dim==dimworld) || (dim==2 && dimworld==3), - "For dim!=dimworld, only the case dim==2 and dimworld==3 is supported!"); - - auto localCosseratEnergy - = std::make_shared<NonplanarCosseratShellEnergy<CompositeBasis, 3, adouble, decltype(creator)> >(materialParameters, - &creator); - - sumEnergy->addLocalEnergy(localCosseratEnergy); - } + sumEnergy->addLocalEnergy(localCosseratEnergy); // The Neumann surface load term auto neumannEnergy = std::make_shared<GFE::NeumannEnergy<CompositeBasis, RealTuple<adouble,3>, Rotation<adouble,3> > >(neumannBoundary,neumannFunction);