diff --git a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc index 2a7c2acb1..d949a1d88 100644 --- a/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc +++ b/src/model/structural_mechanics/structural_mechanics_model_inline_impl.cc @@ -1,381 +1,382 @@ /** * @file structural_mechanics_model_inline_impl.cc * * @author Fabian Barras * @date Thu May 5 19:48:07 2011 * * @brief * * @section LICENSE * * Copyright (©) 2010-2011 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 . * */ /* -------------------------------------------------------------------------- */ template inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize() { AKANTU_DEBUG_TO_IMPLEMENT(); return 0; } template<> inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_2>() { return 2; } template<> inline UInt StructuralMechanicsModel::getTangentStiffnessVoigtSize<_bernoulli_beam_3>() { return 4; } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); SparseMatrix & K = *stiffness_matrix; UInt nb_element = getFEM().getMesh().getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(type); UInt tangent_size = getTangentStiffnessVoigtSize(); Array * tangent_moduli = new Array(nb_element * nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); tangent_moduli->clear(); computeTangentModuli(*tangent_moduli); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = nb_degree_of_freedom * nb_nodes_per_element; Array * bt_d_b = new Array(nb_element*nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); Array * b = new Array(nb_element*nb_quadrature_points, tangent_size*bt_d_b_size, "B"); transferBMatrixToSymVoigtBMatrix(*b); Matrix Bt_D(bt_d_b_size, tangent_size); Matrix BT(tangent_size, bt_d_b_size); Array::iterator< Matrix > B = b->begin(tangent_size, bt_d_b_size); Array::iterator< Matrix > D = tangent_moduli->begin(tangent_size, tangent_size); Array::iterator< Matrix > Bt_D_B = bt_d_b->begin(bt_d_b_size, bt_d_b_size); Array::iterator< Matrix > T = rotation_matrix(type).begin(bt_d_b_size, bt_d_b_size); for (UInt e = 0; e < nb_element; ++e, ++T) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++B, ++D, ++Bt_D_B) { BT.mul(*B, *T); Bt_D.mul(BT, *D); Bt_D_B->mul(Bt_D, BT); } } delete b; delete tangent_moduli; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Array * int_bt_d_b = new Array(nb_element, bt_d_b_size * bt_d_b_size, "int_B^t*D*B"); getFEM().integrate(*bt_d_b, *int_bt_d_b, bt_d_b_size * bt_d_b_size, type); delete bt_d_b; getFEM().assembleMatrix(*int_bt_d_b, K, nb_degree_of_freedom, type); delete int_bt_d_b; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::computeTangentModuli(Array & tangent_moduli) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::transferBMatrixToSymVoigtBMatrix(Array & b, bool local) { AKANTU_DEBUG_TO_IMPLEMENT(); } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::computeStressOnQuad() { AKANTU_DEBUG_IN(); Array & sigma = stress(type, _not_ghost); sigma.clear(); const Mesh & mesh = getFEM().getMesh(); UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(type); UInt tangent_size = getTangentStiffnessVoigtSize(); Array * tangent_moduli = new Array(nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); + tangent_moduli->clear(); computeTangentModuli(*tangent_moduli); /// compute DB UInt d_b_size = nb_degree_of_freedom * nb_nodes_per_element; Array * d_b = new Array(nb_element*nb_quadrature_points, d_b_size * tangent_size, "D*B"); Array * b = new Array(nb_element*nb_quadrature_points, tangent_size*d_b_size, "B"); transferBMatrixToSymVoigtBMatrix(*b); Array::iterator< Matrix > B = b->begin(tangent_size, d_b_size); Array::iterator< Matrix > D = tangent_moduli->begin(tangent_size, tangent_size); Array::iterator< Matrix > D_B = d_b->begin(tangent_size, d_b_size); for (UInt e = 0; e < nb_element; ++e) { for (UInt q = 0; q < nb_quadrature_points; ++q, ++B, ++D, ++D_B) { D_B->mul(*D, *B); } } delete b; delete tangent_moduli; /// compute DBu D_B = d_b->begin(tangent_size, d_b_size); Array::iterator< Vector > DBu = sigma.begin(tangent_size); Vector ul (d_b_size); Array u_el(0, d_b_size); FEM::extractNodalToElementField(mesh, *displacement_rotation, u_el, type); Array::iterator< Vector > ug = u_el.begin(d_b_size); Array::iterator< Matrix > T = rotation_matrix(type).begin(d_b_size, d_b_size); for (UInt e = 0; e < nb_element; ++e, ++T, ++ug) { ul.mul(*T, *ug); for (UInt q = 0; q < nb_quadrature_points; ++q, ++D_B, ++DBu) { DBu->mul(*D_B, ul); } } delete d_b; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::computeForcesByLocalTractionArray(const Array & tractions) { AKANTU_DEBUG_IN(); UInt nb_element = getFEM().getMesh().getNbElement(type); UInt nb_nodes_per_element = getFEM().getMesh().getNbNodesPerElement(type); UInt nb_quad = getFEM().getNbQuadraturePoints(type); // check dimension match AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == getFEM().getElementDimension(), "element type dimension does not match the dimension of boundaries : " << getFEM().getElementDimension() << " != " << Mesh::getSpatialDimension(type)); // check size of the vector AKANTU_DEBUG_ASSERT(tractions.getSize() == nb_quad*nb_element, "the size of the vector should be the total number of quadrature points"); // check number of components AKANTU_DEBUG_ASSERT(tractions.getNbComponent() == nb_degree_of_freedom, "the number of components should be the spatial dimension of the problem"); Array Nvoigt(nb_element * nb_quad, nb_degree_of_freedom * nb_degree_of_freedom * nb_nodes_per_element); transferNMatrixToSymVoigtNMatrix(Nvoigt); Array::const_iterator< Matrix > N_it = Nvoigt.begin(nb_degree_of_freedom, nb_degree_of_freedom * nb_nodes_per_element); Array::const_iterator< Matrix > T_it = rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element, nb_degree_of_freedom * nb_nodes_per_element); Array::const_iterator< Vector > te_it = tractions.begin(nb_degree_of_freedom); Array funct(nb_element * nb_quad, nb_degree_of_freedom * nb_nodes_per_element, 0.); Array::iterator< Vector > Fe_it = funct.begin(nb_degree_of_freedom * nb_nodes_per_element); Vector fe(nb_degree_of_freedom * nb_nodes_per_element); for (UInt e = 0; e < nb_element; ++e, ++T_it) { const Matrix & T = *T_it; for (UInt q = 0; q < nb_quad; ++q, ++N_it, ++te_it, ++Fe_it) { const Matrix & N = *N_it; const Vector & te = *te_it; Vector & Fe = *Fe_it; // compute N^t tl fe.mul(N, te); // turn N^t tl back in the global referential Fe.mul(T, fe); } } // allocate the vector that will contain the integrated values std::stringstream name; name << id << type << ":integral_boundary"; Array int_funct(nb_element, nb_degree_of_freedom * nb_nodes_per_element, name.str()); //do the integration getFEM().integrate(funct, int_funct, nb_degree_of_freedom*nb_nodes_per_element, type); // assemble the result into force vector getFEM().assembleArray(int_funct,*force_momentum, dof_synchronizer->getLocalDOFEquationNumbers(), nb_degree_of_freedom, type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void StructuralMechanicsModel::computeForcesByGlobalTractionArray(const Array & traction_global){ AKANTU_DEBUG_IN(); UInt nb_element = getFEM().getMesh().getNbElement(type); UInt nb_quad = getFEM().getNbQuadraturePoints(type); UInt nb_nodes_per_element = getFEM().getMesh().getNbNodesPerElement(type); std::stringstream name; name << id << ":structuralmechanics:imposed_linear_load"; Array traction_local(nb_element*nb_quad, nb_degree_of_freedom, name.str()); Array::const_iterator< Matrix > T_it = rotation_matrix(type).begin(nb_degree_of_freedom * nb_nodes_per_element, nb_degree_of_freedom * nb_nodes_per_element); Array::const_iterator< Vector > Te_it = traction_global.begin(nb_degree_of_freedom); Array::iterator< Vector > te_it = traction_local.begin(nb_degree_of_freedom); Matrix R(nb_degree_of_freedom, nb_degree_of_freedom); for (UInt e = 0; e < nb_element; ++e, ++T_it) { const Matrix & T = *T_it; for (UInt i = 0; i < nb_degree_of_freedom; ++i) for (UInt j = 0; j < nb_degree_of_freedom; ++j) R(i, j) = T(i, j); for (UInt q = 0; q < nb_quad; ++q, ++Te_it, ++te_it) { const Vector & Te = *Te_it; Vector & te = *te_it; // turn the traction in the local referential te.mul(R, Te); } } computeForcesByLocalTractionArray(traction_local); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @param myf pointer to a function that fills a vector/tensor with respect to * passed coordinates */ template void StructuralMechanicsModel::computeForcesFromFunction(BoundaryFunction myf, BoundaryFunctionType function_type){ /** function type is ** _bft_forces : linear load is given ** _bft_stress : stress function is given -> Not already done for this kind of model */ std::stringstream name; name << id << ":structuralmechanics:imposed_linear_load"; Array lin_load(0, nb_degree_of_freedom,name.str()); name.clear(); UInt offset = nb_degree_of_freedom; //prepare the loop over element types UInt nb_quad = getFEM().getNbQuadraturePoints(type); UInt nb_element = getFEM().getMesh().getNbElement(type); name.clear(); name << id << ":structuralmechanics:quad_coords"; Array quad_coords(nb_element * nb_quad, spatial_dimension, "quad_coords"); getFEMClass().getShapeFunctions().interpolateOnControlPoints(getFEM().getMesh().getNodes(), quad_coords, spatial_dimension); getFEMClass().getShapeFunctions().interpolateOnControlPoints(getFEM().getMesh().getNodes(), quad_coords, spatial_dimension, _not_ghost, empty_filter, true, 0, 1, 1); if(spatial_dimension == 3) getFEMClass().getShapeFunctions().interpolateOnControlPoints(getFEM().getMesh().getNodes(), quad_coords, spatial_dimension, _not_ghost, empty_filter, true, 0, 2, 2); lin_load.resize(nb_element*nb_quad); Real * imposed_val = lin_load.storage(); /// sigma/load on each quadrature points Real * qcoord = quad_coords.storage(); for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { myf(qcoord, imposed_val, NULL, 0); imposed_val += offset; qcoord += spatial_dimension; } } switch(function_type) { case _bft_traction_local: computeForcesByLocalTractionArray(lin_load); break; case _bft_traction: computeForcesByGlobalTractionArray(lin_load); break; default: break; } } /* -------------------------------------------------------------------------- */