From 9ff839890dccb3366e42c8367340c807694d621d Mon Sep 17 00:00:00 2001 From: Lisa Julia Nebel <lisa_julia.nebel@tu-dresden.de> Date: Tue, 20 Oct 2020 14:29:13 +0200 Subject: [PATCH] Refactor parts of surfacecosseratenergy.hh --- dune/gfe/surfacecosseratenergy.hh | 137 ++++++++++++------------------ 1 file changed, 55 insertions(+), 82 deletions(-) diff --git a/dune/gfe/surfacecosseratenergy.hh b/dune/gfe/surfacecosseratenergy.hh index b7b5d122..d6ddb215 100644 --- a/dune/gfe/surfacecosseratenergy.hh +++ b/dune/gfe/surfacecosseratenergy.hh @@ -16,46 +16,20 @@ #include <dune/gfe/tensor3.hh> #include <dune/gfe/vertexnormals.hh> -template <class Basis, std::size_t i> -class LocalFiniteElementFactory -{ -public: - static auto get(const typename Basis::LocalView& localView, - std::integral_constant<std::size_t, i> iType) - -> decltype(localView.tree().child(iType).finiteElement()) - { - return localView.tree().child(iType).finiteElement(); - } -}; - -/** \brief Specialize for scalar bases, here we cannot call tree().child() */ -template <class GridView, int order, std::size_t i> -class LocalFiniteElementFactory<Dune::Functions::LagrangeBasis<GridView,order>,i> -{ -public: - static auto get(const typename Dune::Functions::LagrangeBasis<GridView,order>::LocalView& localView, - std::integral_constant<std::size_t, i> iType) - -> decltype(localView.tree().finiteElement()) - { - return localView.tree().finiteElement(); - } -}; template<class Basis, class TargetSpace, class field_type=double, class GradientRT=double> class SurfaceCosseratEnergy : public Dune::GFE::LocalEnergy<Basis,TargetSpace> { - // grid types - typedef typename Basis::GridView GridView; - typedef typename GridView::ctype ctype; - typedef typename Basis::LocalView::Tree::FiniteElement LocalFiniteElement; - typedef typename GridView::ctype DT; - typedef typename TargetSpace::ctype RT; - typedef typename GridView::template Codim<0>::Entity Entity; - typedef typename TargetSpace::template rebind<adouble>::other ATargetSpace; - - enum {dim=GridView::dimension}; - enum {dimworld=GridView::dimensionworld}; + using GridView = typename Basis::GridView; + using DT = typename GridView::ctype ; + using RT = typename TargetSpace::ctype; + using Entity = typename GridView::template Codim<0>::Entity ; + using RBM0 = RealTuple<RT,GridView::dimensionworld> ; + using RBM1 = Rotation<RT,GridView::dimensionworld> ; + using RBM = RigidBodyMotion<RT,GridView::dimensionworld> ; + + enum {dimWorld=GridView::dimensionworld}; enum {gridDim=GridView::dimension}; static constexpr int boundaryDim = gridDim - 1; @@ -64,9 +38,9 @@ class SurfaceCosseratEnergy \param derivative First derivative of the gfe function wrt x at that point, in quaternion coordinates \param DR First derivative of the gfe function wrt x at that point, in matrix coordinates */ - static void computeDR(const RigidBodyMotion<field_type,dimworld>& value, - const Dune::FieldMatrix<field_type,7,boundaryDim>& derivative, - Tensor3<field_type,3,3,boundaryDim>& DR) + static void computeDR(const RBM& value, + const Dune::FieldMatrix<RT,RBM::embeddedDim,boundaryDim>& derivative, + Tensor3<RT,dimWorld,dimWorld,boundaryDim>& derivative_rotation) { // The LocalGFEFunction class gives us the derivatives of the orientation variable, // but as a map into quaternion space. To obtain matrix coordinates we use the @@ -77,15 +51,15 @@ class SurfaceCosseratEnergy // corresponding orthogonal matrix, we need to invert the i and j indices // // So, DR[i][j][k] contains \partial R_ij / \partial k - Tensor3<field_type,3 , 3, 4> dd_dq; + Tensor3<RT, dimWorld, dimWorld, 4> dd_dq; value.q.getFirstDerivativesOfDirectors(dd_dq); - DR = field_type(0); - for (int i=0; i<3; i++) - for (int j=0; j<3; j++) + derivative_rotation = RT(0); + for (int i=0; i<dimWorld; i++) + for (int j=0; j<dimWorld; j++) for (int k=0; k<boundaryDim; k++) for (int l=0; l<4; l++) - DR[i][j][k] += dd_dq[j][i][l] * derivative[l+3][k]; + derivative_rotation[i][j][k] += dd_dq[j][i][l] * derivative[l+3][k]; } @@ -96,11 +70,11 @@ public: * \param parameters The material parameters */ SurfaceCosseratEnergy(const Dune::ParameterTree& parameters, - const std::vector<UnitVector<double,3> >& vertexNormals, + const std::vector<UnitVector<double,dimWorld> >& vertexNormals, const BoundaryPatch<GridView>* shellBoundary, - const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dim-1, dim>>& geometriesOnShellBoundary, - const std::function<double(Dune::FieldVector<double,dim>)> thicknessF, - const std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF) + const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType,Dune::MultiLinearGeometry<double, dimWorld-1, dimWorld>>& geometriesOnShellBoundary, + const std::function<double(Dune::FieldVector<double,dimWorld>)> thicknessF, + const std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dimWorld>)> lameF) : shellBoundary_(shellBoundary), vertexNormals_(vertexNormals), geometriesOnShellBoundary_(geometriesOnShellBoundary), @@ -120,35 +94,34 @@ public: } RT energy(const typename Basis::LocalView& localView, - const std::vector<RigidBodyMotion<field_type,dim> >& localSolution) const + const std::vector<RigidBodyMotion<field_type,dimWorld> >& localSolution) const { // The element geometry auto element = localView.element(); // The set of shape functions on this element const auto& localFiniteElement = localView.tree().finiteElement(); + auto gridView = localView.globalBasis().gridView(); //////////////////////////////////////////////////////////////////////////////////// // Construct a linear (i.e., non-constant!) normal field on each element //////////////////////////////////////////////////////////////////////////////////// - auto gridView = localView.globalBasis().gridView(); - - assert(vertexNormals_.size() == gridView.indexSet().size(gridDim)); - std::vector<UnitVector<double,3> > cornerNormals(element.subEntities(gridDim)); - for (size_t i=0; i<cornerNormals.size(); i++) - cornerNormals[i] = vertexNormals_[gridView.indexSet().subIndex(element,i,gridDim)]; - typedef typename Dune::PQkLocalFiniteElementCache<DT, double, gridDim, 1> P1FiniteElementCache; typedef typename P1FiniteElementCache::FiniteElementType P1LocalFiniteElement; //it.type()? P1FiniteElementCache p1FiniteElementCache; const auto& p1LocalFiniteElement = p1FiniteElementCache.get(element.type()); + + assert(vertexNormals_.size() == gridView.indexSet().size(gridDim)); + std::vector<UnitVector<double,3> > cornerNormals(element.subEntities(gridDim)); + for (size_t i=0; i<cornerNormals.size(); i++) + cornerNormals[i] = vertexNormals_[gridView.indexSet().subIndex(element,i,gridDim)]; Dune::GFE::LocalProjectedFEFunction<gridDim, DT, P1LocalFiniteElement, UnitVector<double,3> > unitNormals(p1LocalFiniteElement, cornerNormals); //////////////////////////////////////////////////////////////////////////////////// // Set up the local nonlinear finite element function //////////////////////////////////////////////////////////////////////////////////// - typedef LocalGeodesicFEFunction<gridDim, DT, LocalFiniteElement, TargetSpace> LocalGFEFunctionType; + typedef LocalGeodesicFEFunction<gridDim, DT, typename Basis::LocalView::Tree::FiniteElement, TargetSpace> LocalGFEFunctionType; LocalGFEFunctionType localGeodesicFEFunction(localFiniteElement,localSolution); RT energy = 0; @@ -180,7 +153,7 @@ RT energy(const typename Basis::LocalView& localView, const DT integrationElement = boundaryGeometry.integrationElement(quad[pt].position()); // The value of the local function - RigidBodyMotion<field_type,dim> value = localGeodesicFEFunction.evaluate(quadPos); + RigidBodyMotion<field_type,dimWorld> value = localGeodesicFEFunction.evaluate(quadPos); // The derivative of the local function auto derivative = localGeodesicFEFunction.evaluateDerivative(quadPos,value); @@ -196,30 +169,30 @@ RT energy(const typename Basis::LocalView& localView, // Note: we need it in matrix coordinates ////////////////////////////////////////////////////////// - Dune::FieldMatrix<field_type,dim,dim> R; + Dune::FieldMatrix<RT,dimWorld,dimWorld> R; value.q.matrix(R); - auto RT = Dune::GFE::transpose(R); + auto rt = Dune::GFE::transpose(R); - Tensor3<field_type,3,3,boundaryDim> DR; - computeDR(value, derivative2D, DR); + Tensor3<RT,dimWorld,dimWorld,boundaryDim> derivative_rotation; + computeDR(value, derivative2D, derivative_rotation); ////////////////////////////////////////////////////////// // Fundamental forms and curvature ////////////////////////////////////////////////////////// // First fundamental form - Dune::FieldMatrix<double,3,3> aCovariant; + Dune::FieldMatrix<double,dimWorld,dimWorld> aCovariant; - // If dimworld==3, then the first two lines of aCovariant are simply the jacobianTransposed - // of the element. If dimworld<3 (i.e., ==2), we have to explicitly enters 0.0 in the last column. + // If dimWorld==3, then the first two lines of aCovariant are simply the jacobianTransposed + // of the element. If dimWorld<3 (i.e., ==2), we have to explicitly enters 0.0 in the last column. const auto jacobianTransposed = boundaryGeometry.jacobianTransposed(quad[pt].position()); // auto jacobianTransposed = geometry.jacobianTransposed(quadPos); for (int i=0; i<2; i++) { - for (int j=0; j<dimworld; j++) + for (int j=0; j<dimWorld; j++) aCovariant[i][j] = jacobianTransposed[i][j]; - for (int j=dimworld; j<3; j++) + for (int j=dimWorld; j<3; j++) aCovariant[i][j] = 0.0; } @@ -271,28 +244,28 @@ RT energy(const typename Basis::LocalView& localView, ////////////////////////////////////////////////////////// // Elastic shell strain - Dune::FieldMatrix<field_type,3,3> Ee(0); - Dune::FieldMatrix<field_type,3,3> grad_s_m(0); + Dune::FieldMatrix<RT,3,3> Ee(0); + Dune::FieldMatrix<RT,3,3> grad_s_m(0); for (int alpha=0; alpha<boundaryDim; alpha++) { - Dune::FieldVector<field_type,3> vec; + Dune::FieldVector<RT,3> vec; for (int i=0; i<3; i++) vec[i] = derivative[i][alpha]; grad_s_m += Dune::GFE::dyadicProduct(vec, aContravariant[alpha]); } - Ee = RT * grad_s_m - a; + Ee = rt * grad_s_m - a; // Elastic shell bending-curvature strain - Dune::FieldMatrix<field_type,3,3> Ke(0); + Dune::FieldMatrix<RT,3,3> Ke(0); for (int alpha=0; alpha<boundaryDim; alpha++) { - Dune::FieldMatrix<field_type,3,3> tmp; + Dune::FieldMatrix<RT,3,3> tmp; for (int i=0; i<3; i++) for (int j=0; j<3; j++) - tmp[i][j] = DR[i][j][alpha]; - auto tmp2 = RT * tmp; - Ke += Dune::GFE::dyadicProduct(SkewMatrix<field_type,3>(tmp2).axial(), aContravariant[alpha]); + tmp[i][j] = derivative_rotation[i][j][alpha]; + auto tmp2 = rt * tmp; + Ke += Dune::GFE::dyadicProduct(SkewMatrix<RT,3>(tmp2).axial(), aContravariant[alpha]); } ////////////////////////////////////////////////////////// @@ -318,24 +291,24 @@ RT energy(const typename Basis::LocalView& localView, return energy; } - RT W_m(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const + RT W_m(const Dune::FieldMatrix<RT,3,3>& S, double mu, double lambda) const { return W_mixt(S,S, mu, lambda); } - RT W_mixt(const Dune::FieldMatrix<field_type,3,3>& S, const Dune::FieldMatrix<field_type,3,3>& T, double mu, double lambda) const + RT W_mixt(const Dune::FieldMatrix<RT,3,3>& S, const Dune::FieldMatrix<RT,3,3>& T, double mu, double lambda) const { return mu * Dune::GFE::frobeniusProduct(Dune::GFE::sym(S), Dune::GFE::sym(T)) + mu_c_ * Dune::GFE::frobeniusProduct(Dune::GFE::skew(S), Dune::GFE::skew(T)) + lambda * mu / (lambda + 2*mu) * Dune::GFE::trace(S) * Dune::GFE::trace(T); } - RT W_mp(const Dune::FieldMatrix<field_type,3,3>& S, double mu, double lambda) const + RT W_mp(const Dune::FieldMatrix<RT,3,3>& S, double mu, double lambda) const { return mu * Dune::GFE::sym(S).frobenius_norm2() + mu_c_ * Dune::GFE::skew(S).frobenius_norm2() + lambda * 0.5 * Dune::GFE::traceSquared(S); } - RT W_curv(const Dune::FieldMatrix<field_type,3,3>& S, double mu) const + RT W_curv(const Dune::FieldMatrix<RT,3,3>& S, double mu) const { return mu * L_c_ * L_c_ * (b1_ * Dune::GFE::dev(Dune::GFE::sym(S)).frobenius_norm2() + b2_ * Dune::GFE::skew(S).frobenius_norm2() + b3_ * Dune::GFE::traceSquared(S)); @@ -346,16 +319,16 @@ private: const BoundaryPatch<GridView>* shellBoundary_; /** \brief Stress-free geometries of the shell elements*/ - const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType, Dune::MultiLinearGeometry<double, dim-1, dim>> geometriesOnShellBoundary_; + const std::unordered_map<typename GridView::Grid::GlobalIdSet::IdType, Dune::MultiLinearGeometry<double, dimWorld-1, dimWorld>> geometriesOnShellBoundary_; /** \brief The normal vectors at the grid vertices. They are used to compute the reference surface curvature. */ std::vector<UnitVector<double,3> > vertexNormals_; /** \brief The shell thickness as a function*/ - std::function<double(Dune::FieldVector<double,dim>)> thicknessF_; + std::function<double(Dune::FieldVector<double,dimWorld>)> thicknessF_; /** \brief The Lamé-parameters as a function*/ - std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dim>)> lameF_; + std::function<Dune::FieldVector<double,2>(Dune::FieldVector<double,dimWorld>)> lameF_; /** \brief Lame constants */ double mu_, lambda_; -- GitLab