diff --git a/src/fe_engine/element_class_structural.hh b/src/fe_engine/element_class_structural.hh index fca7db751..76732da6a 100644 --- a/src/fe_engine/element_class_structural.hh +++ b/src/fe_engine/element_class_structural.hh @@ -1,279 +1,274 @@ /** * @file element_class_structural.hh * * @author Fabian Barras * @author Lucas Frerot * @author Nicolas Richart * @author Damien Spielmann * * @date creation: Thu Feb 21 2013 * @date last modification: Tue Feb 20 2018 * * @brief Specialization of the element classes for structural elements * * * Copyright (©) 2014-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "element_class.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_ #define AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_ namespace akantu { /// Macro to generate the InterpolationProperty structures for different /// interpolation types #define AKANTU_DEFINE_STRUCTURAL_INTERPOLATION_TYPE_PROPERTY( \ itp_type, itp_geom_type, ndof, nb_stress, nb_dnds_cols) \ template <> struct InterpolationProperty { \ static const InterpolationKind kind{_itk_structural}; \ static const UInt nb_nodes_per_element{ \ InterpolationProperty::nb_nodes_per_element}; \ static const InterpolationType itp_geometry_type{itp_geom_type}; \ static const UInt natural_space_dimension{ \ InterpolationProperty::natural_space_dimension}; \ static const UInt nb_degree_of_freedom{ndof}; \ static const UInt nb_stress_components{nb_stress}; \ static const UInt dnds_columns{nb_dnds_cols}; \ } /* -------------------------------------------------------------------------- */ template class InterpolationElement { public: using interpolation_property = InterpolationProperty; /// compute the shape values for a given set of points in natural coordinates static inline void computeShapes(const Matrix & natural_coord, const Matrix & real_coord, - Tensor3 & N) { + const Matrix & T, Tensor3 & Ns) { for (UInt i = 0; i < natural_coord.cols(); ++i) { - Matrix n_t = N(i); - computeShapes(natural_coord(i), real_coord, n_t); + Matrix N_T = Ns(i); + Matrix N(N_T.rows(), N_T.cols()); + computeShapes(natural_coord(i), real_coord, N); + N_T.mul(N, T); } } /// compute the shape values for a given point in natural coordinates static inline void computeShapes(const Vector & natural_coord, const Matrix & real_coord, Matrix & N); - static inline void computeShapesMass(const Matrix & natural_coord, - const Matrix & real_coord, - Tensor3 & N) { - for (UInt i = 0; i < natural_coord.cols(); ++i) { - Matrix n_t = N(i); - computeShapesMass(natural_coord(i), real_coord, n_t); - } - } - - static inline void computeShapesMass(const Vector & natural_coords, - const Matrix & real_coords, - Matrix & N) { - Matrix Ntotal(interpolation_property::nb_degree_of_freedom, - interpolation_property::nb_degree_of_freedom * - interpolation_property::nb_nodes_per_element); - computeShapes(natural_coords, real_coords, Ntotal); + static inline void computeShapesMass(const Matrix & natural_coords, + const Matrix & xs, + const Matrix & T, + Tensor3 & Ns) { + for (UInt i = 0; i < natural_coords.cols(); ++i) { + Matrix N_T = Ns(i); + Vector X = natural_coords(i); + Matrix N(interpolation_property::nb_degree_of_freedom, N_T.cols()); - N = Ntotal.block(0, 0, N.rows(), N.cols()); + computeShapes(X, xs, N); + N_T.mul(N.block(0, 0, N_T.rows(), N_T.cols()), T); + } } /// compute shape derivatives (input is dxds) for a set of points static inline void computeShapeDerivatives(const Tensor3 & Js, const Tensor3 & DNDSs, const Matrix & R, Tensor3 & Bs) { for (UInt i = 0; i < Js.size(2); ++i) { Matrix J = Js(i); Matrix DNDS = DNDSs(i); Matrix DNDX(DNDS.rows(), DNDS.cols()); auto inv_J = J.inverse(); DNDX.mul(inv_J, DNDS); Matrix B_R = Bs(i); Matrix B(B_R.rows(), B_R.cols()); arrangeInVoigt(DNDX, B); B_R.mul(B, R); } } /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with variation of natural coordinates on a given set * of points in natural coordinates */ static inline void computeDNDS(const Matrix & natural_coord, const Matrix & real_coord, Tensor3 & dnds) { for (UInt i = 0; i < natural_coord.cols(); ++i) { Matrix dnds_t = dnds(i); computeDNDS(natural_coord(i), real_coord, dnds_t); } } /** * compute @f$ B_{ij} = \frac{\partial N_j}{\partial S_i} @f$ the variation of * shape functions along with * variation of natural coordinates on a given point in natural * coordinates */ static inline void computeDNDS(const Vector & natural_coord, const Matrix & real_coord, Matrix & dnds); /** * arrange B in Voigt notation from DNDS */ static inline void arrangeInVoigt(const Matrix & dnds, Matrix & B) { // Default implementation assumes dnds is already in Voigt notation B.deepCopy(dnds); } public: static inline constexpr auto getNbNodesPerInterpolationElement() { return interpolation_property::nb_nodes_per_element; } static inline constexpr auto getShapeSize() { return interpolation_property::nb_nodes_per_element * interpolation_property::nb_degree_of_freedom * interpolation_property::nb_degree_of_freedom; } + static inline constexpr auto getShapeIndependantSize() { + return interpolation_property::nb_nodes_per_element * + interpolation_property::nb_degree_of_freedom * + interpolation_property::nb_stress_components; + } static inline constexpr auto getShapeDerivativesSize() { return interpolation_property::nb_nodes_per_element * interpolation_property::nb_degree_of_freedom * interpolation_property::nb_stress_components; } static inline constexpr auto getNaturalSpaceDimension() { return interpolation_property::natural_space_dimension; } static inline constexpr auto getNbDegreeOfFreedom() { return interpolation_property::nb_degree_of_freedom; } static inline constexpr auto getNbStressComponents() { return interpolation_property::nb_stress_components; } - - static inline constexpr auto getShapeMassSize() { - return interpolation_property::natural_space_dimension * - interpolation_property::nb_degree_of_freedom * - interpolation_property::nb_nodes_per_element; - } }; /// Macro to generate the element class structures for different structural /// element types /* -------------------------------------------------------------------------- */ #define AKANTU_DEFINE_STRUCTURAL_ELEMENT_CLASS_PROPERTY( \ elem_type, geom_type, interp_type, parent_el_type, elem_kind, sp, \ gauss_int_type, min_int_order) \ template <> struct ElementClassProperty { \ static const GeometricalType geometrical_type{geom_type}; \ static const InterpolationType interpolation_type{interp_type}; \ static const ElementType parent_element_type{parent_el_type}; \ static const ElementKind element_kind{elem_kind}; \ static const UInt spatial_dimension{sp}; \ static const GaussIntegrationType gauss_integration_type{gauss_int_type}; \ static const UInt polynomial_degree{min_int_order}; \ } /* -------------------------------------------------------------------------- */ /* ElementClass for structural elements */ /* -------------------------------------------------------------------------- */ template class ElementClass : public GeometricalElement< ElementClassProperty::geometrical_type>, public InterpolationElement< ElementClassProperty::interpolation_type> { protected: using geometrical_element = GeometricalElement::geometrical_type>; using interpolation_element = InterpolationElement< ElementClassProperty::interpolation_type>; using parent_element = ElementClass::parent_element_type>; public: static inline void computeRotationMatrix(Matrix & /*R*/, const Matrix & /*X*/, const Vector & /*extra_normal*/) { AKANTU_TO_IMPLEMENT(); } /// compute jacobian (or integration variable change factor) for a given point static inline void computeJMat(const Vector & natural_coords, const Matrix & Xs, Matrix & J) { Matrix dnds(Xs.rows(), Xs.cols()); parent_element::computeDNDS(natural_coords, dnds); J.mul(dnds, Xs); } static inline void computeJMat(const Matrix & natural_coords, const Matrix & Xs, Tensor3 & Js) { for (UInt i = 0; i < natural_coords.cols(); ++i) { // because non-const l-value reference does not bind to r-value Matrix J = Js(i); computeJMat(Vector(natural_coords(i)), Xs, J); } } static inline void computeJacobian(const Matrix & natural_coords, const Matrix & node_coords, Vector & jacobians) { using itp = typename interpolation_element::interpolation_property; Tensor3 Js(itp::natural_space_dimension, itp::natural_space_dimension, natural_coords.cols()); computeJMat(natural_coords, node_coords, Js); for (UInt i = 0; i < natural_coords.cols(); ++i) { Matrix J = Js(i); jacobians(i) = J.det(); } } static inline void computeRotation(const Matrix & node_coords, Matrix & rotation); public: static AKANTU_GET_MACRO_NOT_CONST(Kind, _ek_structural, ElementKind); static AKANTU_GET_MACRO_NOT_CONST(P1ElementType, _not_defined, ElementType); static AKANTU_GET_MACRO_NOT_CONST(FacetType, _not_defined, ElementType); static constexpr auto getFacetType(__attribute__((unused)) UInt t = 0) { return _not_defined; } static constexpr AKANTU_GET_MACRO_NOT_CONST( SpatialDimension, ElementClassProperty::spatial_dimension, UInt); static constexpr auto getFacetTypes() { return ElementClass<_not_defined>::getFacetTypes(); } }; } // namespace akantu /* -------------------------------------------------------------------------- */ #include "element_class_hermite_inline_impl.hh" /* keep order */ #include "element_class_bernoulli_beam_inline_impl.hh" #include "element_class_kirchhoff_shell_inline_impl.hh" /* -------------------------------------------------------------------------- */ #endif /* AKANTU_ELEMENT_CLASS_STRUCTURAL_HH_ */ diff --git a/src/fe_engine/fe_engine_template_tmpl_field.hh b/src/fe_engine/fe_engine_template_tmpl_field.hh index 4500396b2..bd1b4d5fb 100644 --- a/src/fe_engine/fe_engine_template_tmpl_field.hh +++ b/src/fe_engine/fe_engine_template_tmpl_field.hh @@ -1,500 +1,503 @@ /** * @file fe_engine_template_tmpl_field.hh * * @author Nicolas Richart * * @date creation: Wed Aug 09 2017 * @date last modification: Thu Dec 07 2017 * * @brief implementation of the assemble field s functions * * * Copyright (©) 2016-2018 EPFL (Ecole Polytechnique Fédérale de Lausanne) * Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides) * * Akantu is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * Akantu is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with Akantu. If not, see . * */ /* -------------------------------------------------------------------------- */ #include "fe_engine_template.hh" /* -------------------------------------------------------------------------- */ #ifndef AKANTU_FE_ENGINE_TEMPLATE_TMPL_FIELD_HH_ #define AKANTU_FE_ENGINE_TEMPLATE_TMPL_FIELD_HH_ namespace akantu { /* -------------------------------------------------------------------------- */ /* Matrix lumping functions */ /* -------------------------------------------------------------------------- */ namespace fe_engine { namespace details { namespace { template void fillField(const Functor & field_funct, Array & field, UInt nb_element, UInt nb_integration_points, ElementType type, GhostType ghost_type) { UInt nb_degree_of_freedom = field.getNbComponent(); field.resize(nb_integration_points * nb_element); auto field_it = field.begin_reinterpret( nb_degree_of_freedom, nb_integration_points, nb_element); Element el{type, 0, ghost_type}; for (; el.element < nb_element; ++el.element, ++field_it) { field_funct(*field_it, el); } } } // namespace } // namespace details } // namespace fe_engine /** * Helper class to be able to write a partial specialization on the element kind */ namespace fe_engine { namespace details { template struct AssembleLumpedTemplateHelper { template