diff --git a/common/aka_common.hh b/common/aka_common.hh index 4b9fdaa4c..d649a9b5c 100644 --- a/common/aka_common.hh +++ b/common/aka_common.hh @@ -1,356 +1,380 @@ /** * @file aka_common.hh * @author Nicolas Richart * @date Fri Jun 11 09:48:06 2010 * * @namespace akantu * * @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 . * * @section DESCRIPTION * * All common things to be included in the projects files * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_COMMON_HH__ #define __AKANTU_COMMON_HH__ /* -------------------------------------------------------------------------- */ #include #include #include /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ #define __BEGIN_AKANTU__ namespace akantu { #define __END_AKANTU__ } /* -------------------------------------------------------------------------- */ #include "aka_error.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Common types */ /* -------------------------------------------------------------------------- */ typedef double Real; typedef unsigned int UInt; typedef unsigned long long UInt64; typedef signed int Int; typedef std::string ID; static const Real UINT_INIT_VALUE = 0; #ifdef AKANTU_NDEBUG static const Real REAL_INIT_VALUE = 0; #else static const Real REAL_INIT_VALUE = std::numeric_limits::quiet_NaN(); #endif /* -------------------------------------------------------------------------- */ /* Memory types */ /* -------------------------------------------------------------------------- */ typedef UInt MemoryID; typedef ID VectorID; /* -------------------------------------------------------------------------- */ /* Mesh/FEM/Model types */ /* -------------------------------------------------------------------------- */ typedef ID MeshID; typedef ID FEMID; typedef ID ModelID; typedef ID MaterialID; typedef ID SparseMatrixID; typedef ID SolverID; typedef ID ShapeID; typedef ID IntegratorID; typedef UInt Surface; /* -------------------------------------------------------------------------- */ // BOOST PART: TOUCH ONLY IF YOU KNOW WHAT YOU ARE DOING #include #define AKANTU_BOOST_CASE_MACRO(r,macro,type) \ case type : { macro(type); break;} #define AKANTU_BOOST_ELEMENT_SWITCH(macro); \ do { \ switch(type) { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_CASE_MACRO,macro,AKANTU_ELEMENT_TYPE) \ case _not_defined: \ case _max_element_type: { \ AKANTU_DEBUG_ERROR("Wrong type : " << type); \ break; \ } \ } \ } while(0) #define AKANTU_BOOST_LIST_MACRO(r,macro,type) \ macro(type) #define AKANTU_BOOST_ELEMENT_LIST(macro) \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_LIST_MACRO,macro,AKANTU_ELEMENT_TYPE) /* -------------------------------------------------------------------------- */ /// @boost sequence of element to loop on in global tasks #define AKANTU_ELEMENT_TYPE \ (_segment_2) \ (_segment_3) \ (_triangle_3) \ (_triangle_6) \ (_tetrahedron_4) \ (_tetrahedron_10) \ (_quadrangle_4) \ (_quadrangle_8) \ (_hexahedron_8) \ (_point) /// @enum ElementType type of element potentially contained in a Mesh enum ElementType { _not_defined = 0, _segment_2 = 1, /// first order segment _segment_3 = 2, /// second order segment _triangle_3 = 3, /// first order triangle _triangle_6 = 4, /// second order triangle _tetrahedron_4 = 5, /// first order tetrahedron _tetrahedron_10 = 6, /// second order tetrahedron @remark not implemented yet _quadrangle_4, /// first order quadrangle _quadrangle_8, /// second order quadrangle _hexahedron_8, /// first order hexahedron _point, /// point only for some algorithm to be generic like mesh partitioning - _max_element_type + _max_element_type = 11 }; + + /// @enum MaterialType different materials implemented enum MaterialType { _elastic = 0, _max_material_type }; typedef void (*BoundaryFunction)(double *,double *); /// @enum BoundaryFunctionType type of function passed for boundary conditions enum BoundaryFunctionType { _bft_stress, _bft_forces }; /// @enum SparseMatrixType type of sparse matrix used enum SparseMatrixType { _unsymmetric, _symmetric }; /* -------------------------------------------------------------------------- */ /* Contact */ /* -------------------------------------------------------------------------- */ typedef ID ContactID; typedef ID ContactSearchID; typedef ID ContactNeighborStructureID; enum ContactType { _ct_not_defined = 0, _ct_2d_expli = 1, _ct_3d_expli = 2, _ct_rigid = 3 }; enum ContactSearchType { _cst_not_defined = 0, _cst_2d_expli = 1, _cst_expli = 2 }; enum ContactNeighborStructureType { _cnst_not_defined = 0, _cnst_regular_grid = 1, _cnst_2d_grid = 2 }; /* -------------------------------------------------------------------------- */ /* Ghosts handling */ /* -------------------------------------------------------------------------- */ typedef ID SynchronizerID; /// @enum CommunicatorType type of communication method to use enum CommunicatorType { _communicator_mpi, _communicator_dummy }; /// @enum SynchronizationTag type of synchronizations enum SynchronizationTag { /// SolidMechanicsModel tags _gst_smm_mass, /// synchronization of the SolidMechanicsModel.mass _gst_smm_for_strain, /// synchronization of the SolidMechanicsModel.current_position _gst_smm_boundary, /// synchronization of the boundary, forces, velocities and displacement _gst_smm_uv, /// synchronization of the nodal velocities and displacement /// HeatTransfer tags _gst_htm_capacity, /// synchronization of the nodal heat capacity _gst_htm_temperature, /// synchronization of the nodal temperature _gst_htm_gradient_temperature, /// synchronization of the element gradient temperature /// Test tag _gst_test }; /// @enum GhostType type of ghost enum GhostType { _not_ghost, _ghost, _casper // not used but a real cute ghost }; /// @enum SynchronizerOperation reduce operation that the synchronizer can perform enum SynchronizerOperation { _so_sum, _so_min, _so_max, _so_null }; /* -------------------------------------------------------------------------- */ /* Global defines */ /* -------------------------------------------------------------------------- */ #define AKANTU_MIN_ALLOCATION 2000 #define AKANTU_INDENT " " /* -------------------------------------------------------------------------- */ #define AKANTU_SET_MACRO(name, variable, type) \ inline void set##name (type variable) { \ this->variable = variable; \ } #define AKANTU_GET_MACRO(name, variable, type) \ inline type get##name () const { \ return variable; \ } #define AKANTU_GET_MACRO_NOT_CONST(name, variable, type) \ inline type get##name () { \ return variable; \ } -#define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ - inline type get##name (const ::akantu::ElementType & el_type) const { \ +#define AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(name, variable, type) \ + inline const Vector & \ + get##name (const ::akantu::ElementType & el_type, \ + const GhostType & ghost_type = _not_ghost) const { \ AKANTU_DEBUG_IN(); \ - AKANTU_DEBUG_ASSERT(variable[el_type] != NULL, \ - "No " << #variable << " of type " \ - << el_type << " in " << id); \ + const ByElementTypeVector & const_var = variable; \ AKANTU_DEBUG_OUT(); \ - return *variable[el_type]; \ + return *(const_var(el_type, ghost_type)); \ + } + +#define AKANTU_GET_MACRO_BY_ELEMENT_TYPE(name, variable, type) \ + inline Vector & \ + get##name (const ::akantu::ElementType & el_type, \ + const GhostType & ghost_type = _not_ghost) const { \ + AKANTU_DEBUG_IN(); \ + const ByElementTypeVector & const_var = variable; \ + AKANTU_DEBUG_OUT(); \ + return *(const_var(el_type, ghost_type)); \ } /* -------------------------------------------------------------------------- */ //! standard output stream operator for ElementType inline std::ostream & operator <<(std::ostream & stream, ElementType type) { switch(type) { case _segment_2 : stream << "segment_2" ; break; case _segment_3 : stream << "segment_3" ; break; case _triangle_3 : stream << "triangle_3" ; break; case _triangle_6 : stream << "triangle_6" ; break; case _tetrahedron_4 : stream << "tetrahedron_4" ; break; case _tetrahedron_10 : stream << "tetrahedron_10"; break; case _quadrangle_4 : stream << "quadrangle_4" ; break; case _quadrangle_8 : stream << "quadrangle_8" ; break; case _hexahedron_8 : stream << "hexahedron_8" ; break; case _not_defined : stream << "undefined" ; break; case _max_element_type : stream << "ElementType(" << (int) type << ")"; break; case _point : stream << "point"; break; } return stream; } +/// standard output stream operator for GhostType +inline std::ostream & operator <<(std::ostream & stream, GhostType type) +{ + switch(type) + { + case _not_ghost : stream << "not_ghost"; break; + case _ghost : stream << "ghost" ; break; + case _casper : stream << "Casper the friendly ghost"; break; + } + return stream; +} + /* -------------------------------------------------------------------------- */ void initialize(int * argc, char *** argv); /* -------------------------------------------------------------------------- */ void finalize (); /* -------------------------------------------------------------------------- */ /* * For intel compiler annoying remark */ #if defined(__INTEL_COMPILER) /// remark #981: operands are evaluated in unspecified order #pragma warning ( disable : 981 ) /// remark #383: value copied to temporary, reference to temporary used #pragma warning ( disable : 383 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ /* string manipulation */ /* -------------------------------------------------------------------------- */ inline void to_lower(std::string & str) { std::transform(str.begin(), str.end(), str.begin(), (int(*)(int))std::tolower); } /* -------------------------------------------------------------------------- */ inline void trim(std::string & to_trim) { size_t first = to_trim.find_first_not_of(" \t"); if (first != std::string::npos) { size_t last = to_trim.find_last_not_of(" \t"); to_trim = to_trim.substr(first, last - first + 1); } else to_trim = ""; } __END_AKANTU__ //#include "aka_types.hh" #endif /* __AKANTU_COMMON_HH__ */ diff --git a/common/aka_math_inline_impl.cc b/common/aka_math_inline_impl.cc index 4eb890c16..c8f7c9dd8 100644 --- a/common/aka_math_inline_impl.cc +++ b/common/aka_math_inline_impl.cc @@ -1,476 +1,476 @@ /** * @file aka_math_inline_impl.cc * @author Nicolas Richart * @date Wed Jul 28 13:20:35 2010 * * @brief Implementation of the inline functions of the math toolkit * * @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 . * */ #ifdef AKANTU_USE_BLAS # ifndef AKANTU_USE_BLAS_MKL # include # else // AKANTU_USE_BLAS_MKL # include # endif //AKANTU_USE_BLAS_MKL #endif //AKANTU_USE_BLAS /* -------------------------------------------------------------------------- */ inline void Math::matrix_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y cblas_dgemv(CblasRowMajor, CblasNoTrans, m, n, alpha, A, n, x, 1, 0, y, 1); #else memset(y, 0, m*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * n; for (UInt j = 0; j < n; ++j) { y[i] += A[A_i + j] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_vector(UInt m, UInt n, const Real * A, const Real * x, Real * y, Real alpha) { #ifdef AKANTU_USE_BLAS /// y = alpha*op(A)*x + beta*y cblas_dgemv(CblasRowMajor, CblasNoTrans, m, n, alpha, A, m, x, 1, 0, y, 1); #else memset(y, 0, m*sizeof(Real)); for (UInt i = 0; i < m; ++i) { for (UInt j = 0; j < n; ++j) { y[i] += A[i + j * m] * x[j]; } y[i] *= alpha; } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, m, n, k, alpha, A, k, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[A_i + l] * B[l * n + j]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrix(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasNoTrans, m, n, k, alpha, A, m, B, n, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { // UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[l * n + j]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrix_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasTrans, m, n, k, alpha, A, k, B, k, 0, C, n); #else memset(C, 0, m*n*sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt A_i = i * k; UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { - C[C_i + j] += A[A_i + l] * B[B_j + l]; + C[C_i + j] += A[A_i + l] * B[B_j + l]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ inline void Math::matrixt_matrixt(UInt m, UInt n, UInt k, const Real * A, const Real * B, Real * C, Real alpha) { #ifdef AKANTU_USE_BLAS /// C := alpha*op(A)*op(B) + beta*C cblas_dgemm(CblasRowMajor, CblasTrans, CblasTrans, m, n, k, alpha, A, m, B, k, 0, C, n); #else memset(C, 0, m * n * sizeof(Real)); for (UInt i = 0; i < m; ++i) { UInt C_i = i * n; for (UInt j = 0; j < n; ++j) { UInt B_j = j * k; for (UInt l = 0; l < k; ++l) { C[C_i + j] += A[l * m + i] * B[B_j + l]; } C[C_i + j] *= alpha; } } #endif } /* -------------------------------------------------------------------------- */ template inline void Math::matMul(UInt m, UInt n, UInt k, Real alpha, const Real * A, const Real * B, __attribute__ ((unused)) Real beta, Real * C) { // #ifndef AKANTU_USE_BLAS if(tr_A) { if(tr_B) matrixt_matrixt(m, n, k, A, B, C, alpha); else matrixt_matrix(m, n, k, A, B, C, alpha); } else { if(tr_B) matrix_matrixt(m, n, k, A, B, C, alpha); else matrix_matrix(m, n, k, A, B, C, alpha); } // #else // static CBLAS_TRANSPOSE transpose[2] = {CblasNoTrans, CblasTrans}; // cblas_dgemm(CblasRowMajor, transpose[tr_A], transpose[tr_B], // m, n, k, // alpha, A, m, B, k, // beta, C, n); // #endif } /* -------------------------------------------------------------------------- */ template inline void Math::matVectMul(UInt m, UInt n, Real alpha, const Real * A, const Real * x, __attribute__ ((unused)) Real beta, Real * y) { //#ifndef AKANTU_USE_BLAS if(tr_A) { matrixt_vector(m, n, A, x, y, alpha); } else { matrix_vector(m, n, A, x, y, alpha); } // #else // static CBLAS_TRANSPOSE transpose[2] = {CblasNoTrans, CblasTrans}; // cblas_dgemv(CblasRowMajor, transpose[tr_A], // m, n, // alpha, A, m, x, 1, // beta, y, 1); // #endif } /* -------------------------------------------------------------------------- */ inline Real Math::det2(const Real * mat) { return mat[0]*mat[3] - mat[1]*mat[2]; } /* -------------------------------------------------------------------------- */ inline Real Math::det3(const Real * mat) { return mat[0]*(mat[4]*mat[8]-mat[7]*mat[5]) - mat[3]*(mat[1]*mat[8]-mat[7]*mat[2]) + mat[6]*(mat[1]*mat[5]-mat[4]*mat[2]); } /* -------------------------------------------------------------------------- */ inline void Math::normal2(const Real * vec,Real * normal) { normal[0] = vec[1]; normal[1] = -vec[0]; Math::normalize2(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normal3(const Real * vec1,const Real * vec2,Real * normal) { Math::vectorProduct3(vec1,vec2,normal); Math::normalize3(normal); } /* -------------------------------------------------------------------------- */ inline void Math::normalize2(Real * vec) { Real norm = Math::norm2(vec); vec[0] /= norm; vec[1] /= norm; } /* -------------------------------------------------------------------------- */ inline void Math::normalize3(Real * vec) { Real norm = Math::norm3(vec); vec[0] /= norm; vec[1] /= norm; vec[2] /= norm; } /* -------------------------------------------------------------------------- */ inline Real Math::norm2(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::norm3(const Real * vec) { return sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); } /* -------------------------------------------------------------------------- */ inline void Math::inv2(const Real * mat,Real * inv) { Real det_mat = det2(mat); inv[0] = mat[3] / det_mat; inv[1] = -mat[1] / det_mat; inv[2] = -mat[2] / det_mat; inv[3] = mat[0] / det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::inv3(const Real * mat,Real * inv) { Real det_mat = det3(mat); inv[0] = (mat[4]*mat[8] - mat[7]*mat[5])/det_mat; inv[1] = (mat[2]*mat[7] - mat[8]*mat[1])/det_mat; inv[2] = (mat[1]*mat[5] - mat[4]*mat[2])/det_mat; inv[3] = (mat[5]*mat[6] - mat[8]*mat[3])/det_mat; inv[4] = (mat[0]*mat[8] - mat[6]*mat[2])/det_mat; inv[5] = (mat[2]*mat[3] - mat[5]*mat[0])/det_mat; inv[6] = (mat[3]*mat[7] - mat[6]*mat[4])/det_mat; inv[7] = (mat[1]*mat[6] - mat[7]*mat[0])/det_mat; inv[8] = (mat[0]*mat[4] - mat[3]*mat[1])/det_mat; } /* -------------------------------------------------------------------------- */ inline void Math::vectorProduct3(const Real * v1, const Real * v2, Real * res) { res[0] = v1[1]*v2[2] - v1[2]*v2[1]; res[1] = v1[2]*v2[0] - v1[0]*v2[2]; res[2] = v1[0]*v2[1] - v1[1]*v2[0]; } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot2(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1]); } /* -------------------------------------------------------------------------- */ inline Real Math::vectorDot3(const Real * v1, const Real * v2) { return (v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_2d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1])); } /* -------------------------------------------------------------------------- */ inline Real Math::triangle_inradius(const Real * coord1, const Real * coord2, const Real * coord3) { /** * @f{eqnarray*}{ * r &=& A / s \\ * A &=& 1/4 * \sqrt{(a + b + c) * (a - b + c) * (a + b - c) (-a + b + c)} \\ * s &=& \frac{a + b + c}{2} * @f} */ Real a, b, c; a = distance_2d(coord1, coord2); b = distance_2d(coord2, coord3); c = distance_2d(coord1, coord3); Real s; s = (a + b + c) * 0.5; return sqrt((s - a) * (s - b) * (s - c) / s); } /* -------------------------------------------------------------------------- */ inline Real Math::distance_3d(const Real * x, const Real * y) { return sqrt((y[0] - x[0])*(y[0] - x[0]) + (y[1] - x[1])*(y[1] - x[1]) + (y[2] - x[2])*(y[2] - x[2]) ); } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_volume(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real xx[9], vol; xx[0] = coord2[0]; xx[1] = coord2[1]; xx[2] = coord2[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol = det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord3[0]; xx[4] = coord3[1]; xx[5] = coord3[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol -= det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord4[0]; xx[7] = coord4[1]; xx[8] = coord4[2]; vol += det3(xx); xx[0] = coord1[0]; xx[1] = coord1[1]; xx[2] = coord1[2]; xx[3] = coord2[0]; xx[4] = coord2[1]; xx[5] = coord2[2]; xx[6] = coord3[0]; xx[7] = coord3[1]; xx[8] = coord3[2]; vol -= det3(xx); vol /= 6; return vol; } /* -------------------------------------------------------------------------- */ inline Real Math::tetrahedron_inradius(const Real * coord1, const Real * coord2, const Real * coord3, const Real * coord4) { Real l12, l13, l14, l23, l24, l34; l12 = distance_3d(coord1, coord2); l13 = distance_3d(coord1, coord3); l14 = distance_3d(coord1, coord4); l23 = distance_3d(coord2, coord3); l24 = distance_3d(coord2, coord4); l34 = distance_3d(coord3, coord4); Real s1, s2, s3, s4; s1 = (l12 + l23 + l13) * 0.5; s1 = sqrt(s1*(s1-l12)*(s1-l23)*(s1-l13)); s2 = (l12 + l24 + l14) * 0.5; s2 = sqrt(s2*(s2-l12)*(s2-l24)*(s2-l14)); s3 = (l23 + l34 + l24) * 0.5; s3 = sqrt(s3*(s3-l23)*(s3-l34)*(s3-l24)); s4 = (l13 + l34 + l24) * 0.5; s4 = sqrt(s4*(s4-l13)*(s4-l34)*(s4-l14)); Real volume = Math::tetrahedron_volume(coord1,coord2,coord3,coord4); return 3*volume/(s1+s2+s3+s4); } /* -------------------------------------------------------------------------- */ inline void Math::barycenter(const Real * coord, UInt nb_points, UInt spatial_dimension, Real * barycenter) { memset(barycenter, 0, spatial_dimension * sizeof(Real)); for (UInt n = 0; n < nb_points; ++n) { UInt offset = n * spatial_dimension; for (UInt i = 0; i < spatial_dimension; ++i) { barycenter[i] += coord[offset + i] / (Real) nb_points; } } } /* -------------------------------------------------------------------------- */ inline void Math::vector_2d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; } /* -------------------------------------------------------------------------- */ inline void Math::vector_3d(const Real * x, const Real * y, Real * res) { res[0] = y[0]-x[0]; res[1] = y[1]-x[1]; res[2] = y[2]-x[2]; } /* -------------------------------------------------------------------------- */ inline bool Math::are_float_equal(const Real x, const Real y){ return (std::abs( x - y) < tolerance); } /* -------------------------------------------------------------------------- */ inline bool Math::isnan(Real x) { return ::isnan(x); } /* -------------------------------------------------------------------------- */ inline bool Math::are_vector_equal(UInt n, Real * x, Real * y){ bool test = true; for (UInt i = 0; i < n; ++i) { test &= are_float_equal(x[i],y[i]); } return test; } diff --git a/examples/heat_propagation_explicit/heat_propa_parallel.cc b/examples/heat_propagation_explicit/heat_propa_parallel.cc index 1f3fe21a7..a5c706ce9 100644 --- a/examples/heat_propagation_explicit/heat_propa_parallel.cc +++ b/examples/heat_propagation_explicit/heat_propa_parallel.cc @@ -1,241 +1,241 @@ /** * @file test_heat_transfer_model_cube3d.cc * @author Rui WANG * @date Tue May 17 11:31:22 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" #include "pbc_synchronizer.hh" #include #include #include #include "mesh_partition_scotch.hh" #ifdef AKANTU_USE_QVIEW #include #endif //AKANTU_USE_QVIEW /* -------------------------------------------------------------------------- */ using namespace std; /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER void paraviewInit(const string & name,akantu::HeatTransferModel * model,Dumper & dumper, const akantu::GhostType & ghost_type); void paraviewDump(Dumper & dumper); akantu::UInt spatial_dimension = 3; akantu:: ElementType type = akantu::_tetrahedron_4; akantu::UInt paraview_type = TETRA1; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc,&argv); akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); akantu::debug::setDebugLevel(akantu::dblWarning); std::stringstream filename; filename << "log" << prank; akantu::debug::setLogFile(filename.str()); akantu::HeatTransferModel * model; akantu::MeshPartition * partition = NULL; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("double_cube_tet4.msh", mesh); partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } model = new akantu::HeatTransferModel(mesh); model->initParallel(partition); mesh.computeBoundingBox(); /* -------------------------------------------------------------------------- */ model->readMaterials("material.dat"); model->initModel(); model->initVectors(); model->getTemperature().clear(); model->getTemperatureRate().clear(); // model->getResidual().clear(); // model->getCapacityLumped().clear(); // model->getTemperatureGradient(type).clear(); // model->getTemperatureGradientGhost(type).clear(); /* -------------------------------------------------------------------------- */ model->assembleCapacityLumped(); /* -------------------------------------------------------------------------- */ akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); // akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); /* ------------------------------------------------------------------------ */ //get stable time step akantu::Real time_step = model->getStableTimeStep()*0.8; if (prank == 0) std::cerr << "time step is:"<setTimeStep(time_step); /* -------------------------------------------------------------------------- */ /// boundary conditions const akantu::Vector & nodes = model->getFEM().getMesh().getNodes(); akantu::Vector & boundary = model->getBoundary(); akantu::Vector & temperature = model->getTemperature(); double t1, t2; t1 = 150.; t2 = 100.; for (akantu::UInt i = 0; i < nb_nodes; ++i) { if (mesh.isPureGhostNode(i)) continue; temperature(i) = t2; akantu::Real dz = nodes(i,2) - mesh.getZMin(); // akantu::Real size = mesh.getZMax() - mesh.getZMin(); if(fabs(dz) < 0.1){ boundary(i) = true; temperature(i) = t1; } // else { // temperature(i) = t1-(t1-t2)*dz/size; // } } /* -------------------------------------------------------------------------- */ DumperParaview dumper; DumperParaview dumper_ghost; model->updateResidual(); paraviewInit("heat-test",model,dumper,akantu::_not_ghost); paraviewInit("heat-test",model,dumper_ghost,akantu::_ghost); /* -------------------------------------------------------------------------- */ int max_steps = 10000000; //int max_steps = 100000; /* ------------------------------------------------------------------------ */ #ifdef AKANTU_USE_QVIEW QView qv; qv.setMode(NET_MODE); qv.initLibQview(prank); qv.beginTask("main",max_steps); #endif /* ------------------------------------------------------------------------ */ for(int i=0; iexplicitPred(); model->updateResidual(); model->solveExplicitLumped(); model->explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(i % 1000 == 0){ dumper.Dump(); dumper_ghost.Dump(); } #endif } #ifdef AKANTU_USE_QVIEW qv.endTask(); #endif akantu::finalize(); return 0; } /* -------------------------------------------------------------------------- */ void paraviewInit(const string & name, akantu::HeatTransferModel * model, Dumper & dumper, const akantu::GhostType & ghost_type) { akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type,ghost_type); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); stringstream str; str << name; if (ghost_type == akantu::_ghost) str << "_ghost"; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, str.str().c_str()); if (nb_element) dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type,ghost_type).values, paraview_type, nb_element, C_MODE); else dumper.SetConnectivity(NULL,paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getTemperature().values, 1, "temperature"); dumper.AddNodeDataField(model->getResidual().values, 1, "residual"); dumper.AddNodeDataField(model->getCapacityLumped().values, 1, "capacity_lumped"); if (nb_element){ if (ghost_type == akantu::_ghost) - dumper.AddElemDataField(model->getTemperatureGradientGhost(type).values, + dumper.AddElemDataField(model->getTemperatureGradient(type, akantu::_ghost).values, spatial_dimension, "temperature_gradient"); else dumper.AddElemDataField(model->getTemperatureGradient(type).values, spatial_dimension, "temperature_gradient"); } dumper.SetPrefix("paraview/"); dumper.Init(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { dumper.Dump(); } /* -------------------------------------------------------------------------- */ diff --git a/examples/scalability_test/scalability_test.cc b/examples/scalability_test/scalability_test.cc index e15f8fbc2..3d4884012 100644 --- a/examples/scalability_test/scalability_test.cc +++ b/examples/scalability_test/scalability_test.cc @@ -1,266 +1,270 @@ /** * @file scalability_test.cc * @author Nicolas Richart * @date Tue Feb 22 09:35:58 2011 * * @brief Test de scalability * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "distributed_synchronizer.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ // #ifdef AKANTU_USE_IOHELPER // # include "io_helper.h" // #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { + try { akantu::debug::setDebugLevel(akantu::dblWarning); initialize(&argc, &argv); StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm->getNbProc(); Int prank = comm->whoAmI(); /* -------------------------------------------------------------------------- */ UInt spatial_dimension = 2; ElementType type = _quadrangle_4; UInt max_steps = 100; Real time_factor = 0.2; UInt nex = 100, ney = 100 * psize; Real height = 1., width = 1. * psize; if(argc == 3 || argc == 4) { nex = atoi(argv[1]); ney = atoi(argv[2]); width = ney / 100.; if(argc == 4) { max_steps = atoi(argv[3]); } } else if (argc != 1) { std::cout << "Usage : " << argv[0] << " [nb_x (default 100) nb_y (default 100 * nb proc)] [nb_step (default 100)]" << std::endl; exit(EXIT_FAILURE); } /* ------------------------------------------------------------------------ */ // Real epot, ekin; Mesh mesh(spatial_dimension); if(prank == 0) { std::cout << "Generating mesh..." << std::endl; Real height_el = height / nex; Real width_el = width / ney; UInt nnx = nex + 1, nny = ney + 1; Vector & nodes = const_cast &>(mesh.getNodes()); nodes.resize(nnx * nny); mesh.addConnecticityType(type); + std::cout << mesh < & connectivity = const_cast &>(mesh.getConnectivity(type)); connectivity.resize(nex * ney); for (UInt i = 0; i < nny; ++i) { for (UInt j = 0; j < nnx; ++j) { UInt n = i * nnx + j; nodes.at(n, 0) = i * width_el; nodes.at(n, 1) = j * height_el; } } for (UInt i = 0; i < ney; ++i) { for (UInt j = 0; j < nex; ++j) { UInt e = i * nex + j; connectivity.at(e, 0) = i * nnx + j; connectivity.at(e, 1) = (i + 1) * nnx + j; connectivity.at(e, 2) = (i + 1) * nnx + (j + 1); connectivity.at(e, 3) = i * nnx + j + 1; } } akantu::MeshIOMSH mesh_io; mesh_io.write("bar.msh", mesh); } MPI_Barrier(MPI_COMM_WORLD); akantu::MeshPartition * partition = NULL; if(prank == 0) { std::cout << "Partitioning mesh..." << std::endl; partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } akantu::SolidMechanicsModel * model = new akantu::SolidMechanicsModel(mesh); model->initParallel(partition); /// model initialization model->initVectors(); /// set vectors to 0 akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(akantu::Real)); model->initExplicit(); model->initModel(); model->readMaterials("material.dat"); model->initMaterials(); model->assembleMassLumped(); // std::cout << model->getMaterial(0) << std::endl; /// boundary conditions akantu::Real eps = 1e-16; for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= (width * .9)) model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - .9 * width) / 100. ; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= (height - eps) ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } // #ifdef AKANTU_USE_IOHELPER // akantu::UInt paraview_type = QUAD1; // double * part; // akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); // /// set to 0 only for the first paraview dump // memset(model->getResidual().values, 0, // spatial_dimension*nb_nodes*sizeof(akantu::Real)); // memset(model->getMaterial(0).getStrain(type).values, 0, // spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); // memset(model->getMaterial(0).getStress(type).values, 0, // spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); // DumperParaview dumper; // dumper.SetMode(BASE64); // dumper.SetParallelContext(prank, psize); // dumper.SetPoints(model->getFEM().getMesh().getNodes().values, // spatial_dimension, nb_nodes, "coordinates"); // dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, // paraview_type, nb_element, C_MODE); // dumper.AddNodeDataField(model->getDisplacement().values, // spatial_dimension, "displacements"); // dumper.AddNodeDataField(model->getVelocity().values, // spatial_dimension, "velocity"); // dumper.AddNodeDataField(model->getResidual().values, // spatial_dimension, "force"); // dumper.AddElemDataField(model->getMaterial(0).getStrain(type).values, // spatial_dimension*spatial_dimension, "strain"); // dumper.AddElemDataField(model->getMaterial(0).getStress(type).values, // spatial_dimension*spatial_dimension, "stress"); // akantu::UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(type); // part = new double[nb_element*nb_quadrature_points]; // for (unsigned int i = 0; i < nb_element; ++i) // for (unsigned int q = 0; q < nb_quadrature_points; ++q) // part[i*nb_quadrature_points + q] = prank; // dumper.AddElemDataField(part, 1, "partitions"); // dumper.SetEmbeddedValue("displacements", 1); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); // #endif //AKANTU_USE_IOHELPER akantu::Real time_step = model->getStableTimeStep() * time_factor; model->setTimeStep(time_step); // std::ofstream energy; // energy.open("energy.csv"); // energy << "id,epot,ekin,tot" << std::endl; double total_time = 0.; if(prank == 0) { std::cout << "Time Step = " << time_step << "s" << std::endl; std::cerr << "passing step " << 0 << "/" << max_steps << std::endl; } for(akantu::UInt s = 1; s <= max_steps; ++s) { double start = MPI_Wtime(); model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); double end = MPI_Wtime(); total_time += end - start; // epot = model->getPotentialEnergy(); // ekin = model->getKineticEnergy(); if(s % (std::max(1,(int)max_steps/10)) == 0 && prank == 0) { std::cerr << "passing step " << s << "/" << max_steps << std::endl; } // energy << s << "," << epot << "," << ekin << "," << epot + ekin // << std::endl; // #ifdef AKANTU_USE_IOHELPER // if(s % 10 == 0) { // dumper.Dump(); // } // #endif //AKANTU_USE_IOHELPER } if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; // #ifdef AKANTU_USE_IOHELPER // delete [] part; // #endif //AKANTU_USE_IOHELPER // energy.close(); finalize(); - + } catch(std::exception & e) { + std::cout << e.what() << std::endl; + } return EXIT_SUCCESS; } diff --git a/fem/fem.cc b/fem/fem.cc index bac760529..feb517217 100644 --- a/fem/fem.cc +++ b/fem/fem.cc @@ -1,236 +1,234 @@ /** * @file fem.cc * @author Nicolas Richart * @author Guillaume Anciaux * @date Fri Jul 16 11:03:02 2010 * * @brief Implementation of the FEM class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "fem.hh" #include "mesh.hh" #include "element_class.hh" #include "static_communicator.hh" #include "aka_math.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ FEM::FEM(Mesh & mesh, UInt element_dimension, FEMID id, MemoryID memory_id) : Memory(memory_id), id(id) { AKANTU_DEBUG_IN(); this->element_dimension = (element_dimension != 0) ? element_dimension : mesh.getSpatialDimension(); init(); this->mesh = &mesh; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::init() { - for(UInt t = _not_defined; t < _max_element_type; ++t) { - this->normals_on_quad_points[t] = NULL; - } + } /* -------------------------------------------------------------------------- */ FEM::~FEM() { AKANTU_DEBUG_IN(); mesh = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::assembleVector(const Vector & elementary_vect, Vector & nodal_values, const Vector & equation_number, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements, Real scale_factor) const { AKANTU_DEBUG_IN(); UInt nb_element = mesh->getNbElement(type,ghost_type); UInt * conn_val = mesh->getConnectivity(type,ghost_type).values; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_nodes = mesh->getNbNodes(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(elementary_vect.getSize() == nb_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(elementary_vect.getNbComponent() == nb_degre_of_freedom*nb_nodes_per_element, "The vector elementary_vect(" << elementary_vect.getID() << ") has not the good number of component." << "(" << elementary_vect.getNbComponent() << " != " << nb_degre_of_freedom*nb_nodes_per_element << ")"); AKANTU_DEBUG_ASSERT(nodal_values.getNbComponent() == nb_degre_of_freedom, "The vector nodal_values(" << nodal_values.getID() << ") has not the good number of component." << "(" << nodal_values.getNbComponent() << " != " << nb_degre_of_freedom << ")"); nodal_values.resize(nb_nodes); Real * elementary_vect_val = elementary_vect.values; Real * nodal_values_val = nodal_values.values; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = conn_val[el_offset + n]; UInt offset_node = node * nb_degre_of_freedom; for (UInt d = 0; d < nb_degre_of_freedom; ++d) { nodal_values_val[equation_number.values[offset_node + d]] += scale_factor * elementary_vect_val[d]; } elementary_vect_val += nb_degre_of_freedom; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::assembleMatrix(const Vector & elementary_mat, SparseMatrix & matrix, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); UInt nb_element; if(ghost_type == _not_ghost) { nb_element = mesh->getNbElement(type); } else { AKANTU_DEBUG_TO_IMPLEMENT(); } UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(elementary_mat.getSize() == nb_element, "The vector elementary_mat(" << elementary_mat.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(elementary_mat.getNbComponent() == nb_degre_of_freedom * nb_nodes_per_element * nb_degre_of_freedom * nb_nodes_per_element, "The vector elementary_mat(" << elementary_mat.getID() << ") has not the good number of component."); Real * elementary_mat_val = elementary_mat.values; UInt offset_elementary_mat = elementary_mat.getNbComponent(); - UInt * connectivity_val = mesh->getConnectivity(type).values; + UInt * connectivity_val = mesh->getConnectivity(type, ghost_type).values; UInt size_mat = nb_nodes_per_element * nb_degre_of_freedom; UInt size = mesh->getNbGlobalNodes() * nb_degre_of_freedom; Int * eq_nb_val = matrix.getDOFSynchronizer().getGlobalDOFEquationNumbers().values; Int * local_eq_nb_val = new Int[nb_degre_of_freedom * nb_nodes_per_element]; for (UInt e = 0; e < nb_element; ++e) { UInt el = e; if(filter_elements != NULL) el = filter_elem_val[e]; Int * tmp_local_eq_nb_val = local_eq_nb_val; UInt * conn_val = connectivity_val + el * nb_nodes_per_element; for (UInt i = 0; i < nb_nodes_per_element; ++i) { UInt n = conn_val[i]; for (UInt d = 0; d < nb_degre_of_freedom; ++d) { *tmp_local_eq_nb_val++ = eq_nb_val[n * nb_degre_of_freedom + d]; } // memcpy(tmp_local_eq_nb_val, eq_nb_val + n * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Int)); // tmp_local_eq_nb_val += nb_degre_of_freedom; } for (UInt i = 0; i < size_mat; ++i) { UInt c_irn = local_eq_nb_val[i]; if(c_irn < size) { UInt j_start = (matrix.getSparseMatrixType() == _symmetric) ? i : 0; for (UInt j = j_start; j < size_mat; ++j) { UInt c_jcn = local_eq_nb_val[j]; if(c_jcn < size) { matrix(c_irn, c_jcn) += elementary_mat_val[i * size_mat + j]; } } } } elementary_mat_val += offset_elementary_mat; } delete [] local_eq_nb_val; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void FEM::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "FEM [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + element dimension : " << element_dimension << std::endl; stream << space << " + mesh [" << std::endl; mesh->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + mesh [" << std::endl; mesh->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } __END_AKANTU__ diff --git a/fem/fem.hh b/fem/fem.hh index fa4b9b45e..b5ec8b6da 100644 --- a/fem/fem.hh +++ b/fem/fem.hh @@ -1,232 +1,234 @@ /** * @file fem.hh * @author Nicolas Richart * @date Fri Jul 16 10:24:24 2010 * * @brief FEM class * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_FEM_HH__ #define __AKANTU_FEM_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "mesh.hh" #include "element_class.hh" #include "sparse_matrix.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class FEM : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEM(Mesh & mesh, UInt spatial_dimension = 0, FEMID id = "fem", MemoryID memory_id = 0); virtual ~FEM(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// build the profile of the sparse matrix corresponding to the mesh void initSparseMatrixProfile(SparseMatrixType sparse_matrix_type = _unsymmetric); /// pre-compute all the shape functions, their derivatives and the jacobians - virtual void initShapeFunctions(GhostType ghost_type = _not_ghost)=0; + virtual void initShapeFunctions(const GhostType & ghost_type = _not_ghost) = 0; /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" virtual void integrate(const Vector & f, Vector &intf, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; /// integrate a scalar value on all elements of type "type" virtual Real integrate(const Vector & f, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const = 0; /* ------------------------------------------------------------------------ */ /* compatibility with old FEM fashion */ /* ------------------------------------------------------------------------ */ /// get the number of quadrature points - virtual UInt getNbQuadraturePoints(const ElementType & type)=0; + virtual UInt getNbQuadraturePoints(const ElementType & type, + const GhostType & ghost_type = _not_ghost) = 0; /// get the precomputed shapes const virtual Vector & getShapes(const ElementType & type, - const GhostType & ghost_type = _not_ghost)=0; + const GhostType & ghost_type = _not_ghost) = 0; /// get the derivatives of shapes const virtual Vector & getShapesDerivatives(const ElementType & type, - const GhostType & ghost_type = _not_ghost)=0; + const GhostType & ghost_type = _not_ghost) = 0; /// get quadrature points - const virtual Vector & getQuadraturePoints(const ElementType & type)=0; + const virtual Vector & getQuadraturePoints(const ElementType & type, + const GhostType & ghost_type = _not_ghost) = 0; /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ virtual void gradientOnQuadraturePoints(const Vector &u, Vector &nablauq, const UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL)=0; virtual void interpolateOnQuadraturePoints(const Vector &u, Vector &uq, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const =0; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points - virtual void computeNormalsOnControlPoints(GhostType ghost_type = _not_ghost)=0; + virtual void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost)=0; /// assemble vectors void assembleVector(const Vector & elementary_vect, Vector & nodal_values, const Vector & equation_number, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL, Real scale_factor = 1) const; /// assemble matrix in the complete sparse matrix void assembleMatrix(const Vector & elementary_mat, SparseMatrix & matrix, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// assemble a field as a lumped matrix (ex. rho in lumped mass) virtual void assembleFieldLumped(__attribute__ ((unused)) const Vector & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) Vector & lumped, __attribute__ ((unused)) const Vector & equation_number, __attribute__ ((unused)) ElementType type, - __attribute__ ((unused)) __attribute__ ((unused)) GhostType ghost_type) { + __attribute__ ((unused)) __attribute__ ((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); }; /// assemble a field as a matrix (ex. rho to mass matrix) virtual void assembleFieldMatrix(__attribute__ ((unused)) const Vector & field_1, __attribute__ ((unused)) UInt nb_degree_of_freedom, __attribute__ ((unused)) SparseMatrix & matrix, __attribute__ ((unused)) ElementType type, - __attribute__ ((unused)) GhostType ghost_type) { + __attribute__ ((unused)) const GhostType & ghost_type) { AKANTU_DEBUG_TO_IMPLEMENT(); } /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// initialise the class void init(); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ElementDimension, element_dimension, UInt); /// get the mesh contained in the fem object inline Mesh & getMesh() const; /// get the in-radius of an element static inline Real getElementInradius(Real * coord, const ElementType & type); /// get the normals on quadrature points - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NormalsOnQuadPoints, normals_on_quad_points, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NormalsOnQuadPoints, normals_on_quad_points, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the fem object FEMID id; /// spatial dimension of the problem UInt element_dimension; /// the mesh on which all computation are made Mesh * mesh; /// normals at quadrature points ByElementTypeReal normals_on_quad_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "fem_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const FEM & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #include "fem_template.hh" #endif /* __AKANTU_FEM_HH__ */ diff --git a/fem/fem_template.cc b/fem/fem_template.cc index 36853f822..b5bb7a671 100644 --- a/fem/fem_template.cc +++ b/fem/fem_template.cc @@ -1,597 +1,590 @@ /** * @file fem_template.cc * @author Guillaume Anciaux * @author Nicolas Richart * @date Fri Feb 11 11:37:47 2011 * * @brief implementation of the generic FEMTemplate class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "fem.hh" #include "aka_common.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ - template FEMTemplate::FEMTemplate(Mesh & mesh, UInt spatial_dimension, FEMID id,MemoryID memory_id) :FEM(mesh,spatial_dimension,id,memory_id), integrator(mesh), shape_functions(mesh) { } -/* -------------------------------------------------------------------------- */ - +/* -------------------------------------------------------------------------- */ template FEMTemplate::~FEMTemplate() { } /* -------------------------------------------------------------------------- */ - template void FEMTemplate::gradientOnQuadraturePoints(const Vector &u, Vector &nablauq, const UInt nb_degree_of_freedom, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements){ AKANTU_DEBUG_IN(); #define COMPUTE_GRADIENT(type) \ if (element_dimension == ElementClass::getSpatialDimension()) \ shape_functions.template gradientOnControlPoints(u, \ nablauq, \ nb_degree_of_freedom, \ ghost_type, \ filter_elements); AKANTU_BOOST_ELEMENT_SWITCH(COMPUTE_GRADIENT); #undef COMPUTE_GRADIENT AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ - template -void FEMTemplate::initShapeFunctions(GhostType ghost_type){ +void FEMTemplate::initShapeFunctions(const GhostType & ghost_type){ AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh->getSpatialDimension(); const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; #define INIT_SHAPE_FUNCTIONS(type) \ if (element_dimension != ElementClass::getSpatialDimension()) \ continue; \ - integrator.template computeQuadraturePoints(); \ + integrator.template computeQuadraturePoints(ghost_type); \ integrator. \ template precomputeJacobiansOnQuadraturePoints(ghost_type); \ integrator. \ template checkJacobians(ghost_type); \ Vector & control_points = \ - integrator.template getQuadraturePoints(); \ + integrator.template getQuadraturePoints(ghost_type); \ shape_functions. \ - template setControlPointsByType(control_points); \ + template setControlPointsByType(control_points, ghost_type); \ shape_functions. \ template precomputeShapesOnControlPoints(ghost_type); \ if (element_dimension == spatial_dimension) \ shape_functions. \ template precomputeShapeDerivativesOnControlPoints(ghost_type); - + AKANTU_BOOST_ELEMENT_SWITCH(INIT_SHAPE_FUNCTIONS); #undef INIT_SHAPE_FUNCTIONS } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void FEMTemplate::integrate(const Vector & f, Vector &intf, UInt nb_degree_of_freedom, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements) const{ #define INTEGRATE(type) \ integrator.template integrate(f, \ intf, \ nb_degree_of_freedom, \ ghost_type, \ filter_elements); AKANTU_BOOST_ELEMENT_SWITCH(INTEGRATE); #undef INTEGRATE } /* -------------------------------------------------------------------------- */ template Real FEMTemplate::integrate(const Vector & f, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements) const{ AKANTU_DEBUG_IN(); Real integral = 0.; #define INTEGRATE(type) \ integral = integrator.template integrate(f, \ ghost_type, \ filter_elements); AKANTU_BOOST_ELEMENT_SWITCH(INTEGRATE); #undef INTEGRATE AKANTU_DEBUG_OUT(); return integral; } /* -------------------------------------------------------------------------- */ template void FEMTemplate::interpolateOnQuadraturePoints(const Vector &u, Vector &uq, UInt nb_degree_of_freedom, const ElementType & type, - GhostType ghost_type, + const GhostType & ghost_type, const Vector * filter_elements) const{ AKANTU_DEBUG_IN(); #define INTERPOLATE(type) \ shape_functions.template interpolateOnControlPoints(u, \ uq, \ nb_degree_of_freedom, \ ghost_type, \ filter_elements); AKANTU_BOOST_ELEMENT_SWITCH(INTERPOLATE); #undef INTERPOLATE AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template -void FEMTemplate::computeNormalsOnControlPoints(GhostType ghost_type) { +void FEMTemplate::computeNormalsOnControlPoints(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); + if (ghost_type == _ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); } + // Real * coord = mesh->getNodes().values; UInt spatial_dimension = mesh->getSpatialDimension(); //allocate the normal arrays - if (ghost_type == _not_ghost) - mesh->initByElementTypeRealVector(normals_on_quad_points,spatial_dimension,element_dimension, - id,"normals_onquad",ghost_type); - else{ - AKANTU_DEBUG_ERROR("to be implemented"); - } + mesh->initByElementTypeVector(normals_on_quad_points,spatial_dimension,element_dimension, + id,"normals_onquad"); //loop over the type to build the normals const Mesh::ConnectivityTypeList & type_list = mesh->getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; UInt element_type_spatial_dimension = Mesh::getSpatialDimension(type); if(element_type_spatial_dimension != element_dimension) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_quad_points = getQuadraturePoints(type).getSize(); - UInt * elem_val = mesh->getConnectivity(type,ghost_type).values; - UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize(); + UInt nb_quad_points = getQuadraturePoints(type, ghost_type).getSize(); + UInt * elem_val = mesh->getConnectivity(type, ghost_type).values; + UInt nb_element = mesh->getConnectivity(type, ghost_type).getSize(); - Real * normals_on_quad_val = NULL; - - if(ghost_type == _not_ghost) { - normals_on_quad_points[type]->resize(nb_element * nb_quad_points); - normals_on_quad_val = normals_on_quad_points[type]->values; - } else { - //TODO something should be done here ? - } + Vector * normals_on_quad = normals_on_quad_points(type, ghost_type); + normals_on_quad->resize(nb_element * nb_quad_points); + Real * normals_on_quad_val = normals_on_quad->values; /* ---------------------------------------------------------------------- */ #define COMPUTE_NORMALS_ON_QUAD(type) \ do { \ - Vector & quads = integrator. template getQuadraturePoints(); \ + Vector & quads = \ + integrator. template getQuadraturePoints(ghost_type); \ UInt nb_points = quads.getSize(); \ Real local_coord[spatial_dimension * nb_nodes_per_element]; \ for (UInt elem = 0; elem < nb_element; ++elem) { \ mesh->extractNodalCoordinatesFromElement(local_coord, \ elem_val+elem*nb_nodes_per_element, \ nb_nodes_per_element); \ ElementClass::computeNormalsOnQuadPoint(local_coord, \ spatial_dimension, \ normals_on_quad_val); \ normals_on_quad_val += spatial_dimension*nb_points; \ } \ } while(0) /* ---------------------------------------------------------------------- */ AKANTU_BOOST_ELEMENT_SWITCH(COMPUTE_NORMALS_ON_QUAD); #undef COMPUTE_NORMALS_ON_QUAD } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* compatibility functions */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template -inline UInt FEMTemplate::getNbQuadraturePoints(const ElementType & type) { +inline UInt FEMTemplate::getNbQuadraturePoints(const ElementType & type, + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_quad_points = 0; #define GET_NB_QUAD(type) \ - nb_quad_points = integrator. template getQuadraturePoints().getSize(); + nb_quad_points = \ + integrator. template getQuadraturePoints(ghost_type).getSize(); AKANTU_BOOST_ELEMENT_SWITCH(GET_NB_QUAD); #undef GET_NB_QUAD AKANTU_DEBUG_OUT(); return nb_quad_points; } /* -------------------------------------------------------------------------- */ template inline const Vector & FEMTemplate::getShapes(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Vector * ret = NULL; #define GET_SHAPES(type) \ - ret = &(shape_functions.getShapes(type,ghost_type)); + ret = &(shape_functions.getShapes(type, ghost_type)); AKANTU_BOOST_ELEMENT_SWITCH(GET_SHAPES); #undef GET_SHAPES AKANTU_DEBUG_OUT(); return *ret; } /* -------------------------------------------------------------------------- */ template inline const Vector & FEMTemplate::getShapesDerivatives(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Vector * ret = NULL; #define GET_SHAPES(type) \ - ret = &(shape_functions.getShapesDerivatives(type,ghost_type)); + ret = &(shape_functions.getShapesDerivatives(type, ghost_type)); AKANTU_BOOST_ELEMENT_SWITCH(GET_SHAPES); #undef GET_SHAPES AKANTU_DEBUG_OUT(); return *ret; } /* -------------------------------------------------------------------------- */ template -inline const Vector & FEMTemplate::getQuadraturePoints(const ElementType & type) { +inline const Vector & FEMTemplate::getQuadraturePoints(const ElementType & type, + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Vector * ret = NULL; #define GET_QUADS(type) \ - ret = &(integrator. template getQuadraturePoints()); + ret = &(integrator. template getQuadraturePoints(ghost_type)); AKANTU_BOOST_ELEMENT_SWITCH(GET_QUADS); #undef GET_QUADS AKANTU_DEBUG_OUT(); return *ret; } /* -------------------------------------------------------------------------- */ /* Matrix lumping functions */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ template void FEMTemplate::assembleFieldLumped(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, ElementType type, - GhostType ghost_type) { + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); #define ASSEMBLE_LUMPED(type) \ assembleLumpedTemplate(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type) AKANTU_BOOST_ELEMENT_SWITCH(ASSEMBLE_LUMPED);; #undef ASSEMBLE_LUMPED AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void FEMTemplate::assembleFieldMatrix(const Vector & field_1, UInt nb_degree_of_freedom, SparseMatrix & matrix, ElementType type, - GhostType ghost_type) { + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); #define ASSEMBLE_MATRIX(type) \ assembleFieldMatrix(field_1, nb_degree_of_freedom, \ matrix, \ ghost_type) AKANTU_BOOST_ELEMENT_SWITCH(ASSEMBLE_MATRIX);; #undef ASSEMBLE_MATRIX AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template template void FEMTemplate::assembleLumpedTemplate(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { this->template assembleLumpedRowSum(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type); } /* -------------------------------------------------------------------------- */ //template template <> template <> void FEMTemplate:: assembleLumpedTemplate<_triangle_6>(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { assembleLumpedDiagonalScaling<_triangle_6>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> void FEMTemplate:: assembleLumpedTemplate<_tetrahedron_10>(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { assembleLumpedDiagonalScaling<_tetrahedron_10>(field_1, nb_degree_of_freedom,lumped, equation_number,ghost_type); } /* -------------------------------------------------------------------------- */ template <> template <> void FEMTemplate::assembleLumpedTemplate<_quadrangle_8>(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { assembleLumpedDiagonalScaling<_quadrangle_8>(field_1, nb_degree_of_freedom,lumped, equation_number, ghost_type); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$ */ template template void FEMTemplate::assembleLumpedRowSum(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt shapes_size = ElementClass::getShapeSize(); Vector * field_times_shapes = new Vector(0, 1);//shapes_size); shape_functions.template fieldTimesShapes(field_1, *field_times_shapes, ghost_type); Vector * int_field_times_shapes = new Vector(0, shapes_size, "inte_rho_x_shapes"); integrator.template integrate(*field_times_shapes, *int_field_times_shapes, shapes_size, ghost_type, NULL); delete field_times_shapes; int_field_times_shapes->extendComponentsInterlaced(nb_degree_of_freedom,1); assembleVector(*int_field_times_shapes, lumped, equation_number,nb_degree_of_freedom, type, ghost_type); delete int_field_times_shapes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = c * M_{ii} = \int_{V_e} \rho dV @f$ */ template template void FEMTemplate::assembleLumpedDiagonalScaling(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type) { + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element_p1 = Mesh::getNbNodesPerElement(Mesh::getP1ElementType(type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_quadrature_points = integrator.template getQuadraturePoints().getSize(); + UInt nb_quadrature_points = integrator.template getQuadraturePoints(ghost_type).getSize(); UInt nb_element = field_1.getSize() / nb_quadrature_points; Real corner_factor = 0; Real mid_factor = 0; if(type == _triangle_6) { corner_factor = 1./12.; mid_factor = 1./4.; } if (type == _tetrahedron_10) { corner_factor = 1./32.; mid_factor = 7./48.; } if (type == _quadrangle_8) { corner_factor = 1./36.; mid_factor = 8./36.; } if (nb_element == 0) { AKANTU_DEBUG_OUT(); return; } /// compute @f$ \int \rho dV = \rho V @f$ for each element Vector * int_field_1 = new Vector(field_1.getSize(), 1, "inte_rho_x_1"); integrator.template integrate(field_1, *int_field_1, 1, ghost_type, NULL); /// distribute the mass of the element to the nodes Vector * lumped_per_node = new Vector(nb_element, nb_nodes_per_element, "mass_per_node"); Real * int_field_1_val = int_field_1->values; Real * lumped_per_node_val = lumped_per_node->values; for (UInt e = 0; e < nb_element; ++e) { Real lmass = *int_field_1_val * corner_factor; for (UInt n = 0; n < nb_nodes_per_element_p1; ++n) *lumped_per_node_val++ = lmass; /// corner points lmass = *int_field_1_val * mid_factor; for (UInt n = nb_nodes_per_element_p1; n < nb_nodes_per_element; ++n) *lumped_per_node_val++ = lmass; /// mid points int_field_1_val++; } delete int_field_1; lumped_per_node->extendComponentsInterlaced(nb_degree_of_freedom,1); assembleVector(*lumped_per_node, lumped, equation_number, nb_degree_of_freedom, type, ghost_type); delete lumped_per_node; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * @f$ \tilde{M}_{i} = \sum_j M_{ij} = \sum_j \int \rho \varphi_i \varphi_j dV = \int \rho \varphi_i dV @f$ */ template template void FEMTemplate::assembleFieldMatrix(const Vector & field_1, UInt nb_degree_of_freedom, SparseMatrix & matrix, - GhostType ghost_type) { + const GhostType & ghost_type) { AKANTU_DEBUG_IN(); UInt vect_size = field_1.getSize(); UInt shapes_size = ElementClass::getShapeSize(); UInt lmat_size = nb_degree_of_freedom * shapes_size; const Vector & shapes = shape_functions.getShapes(type,ghost_type); Vector * modified_shapes = new Vector(vect_size, lmat_size * nb_degree_of_freedom); modified_shapes->clear(); Vector * local_mat = new Vector(vect_size, lmat_size * lmat_size); Vector::iterator shape_vect = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Real * sh = shapes.values; for(UInt q = 0; q < vect_size; ++q) { Real * msh = shape_vect->storage(); for (UInt d = 0; d < nb_degree_of_freedom; ++d) { Real * msh_tmp = msh + d * (lmat_size + 1); for (UInt s = 0; s < shapes_size; ++s) { *msh_tmp = sh[s]; msh_tmp += nb_degree_of_freedom; } } ++shape_vect; sh += shapes_size; } shape_vect = modified_shapes->begin(nb_degree_of_freedom, lmat_size); Vector::iterator lmat = local_mat->begin(lmat_size, lmat_size); Real * field_val = field_1.values; for(UInt q = 0; q < vect_size; ++q) { (*lmat).mul(*shape_vect, *shape_vect, *field_val); ++lmat; ++shape_vect; ++field_val; } delete modified_shapes; Vector * int_field_times_shapes = new Vector(0, lmat_size * lmat_size, "inte_rho_x_shapes"); integrator.template integrate(*local_mat, *int_field_times_shapes, lmat_size * lmat_size, ghost_type, NULL); delete local_mat; assembleMatrix(*int_field_times_shapes, matrix, nb_degree_of_freedom, type, ghost_type); delete int_field_times_shapes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* template instanciation */ /* -------------------------------------------------------------------------- */ template class FEMTemplate; __END_AKANTU__ diff --git a/fem/fem_template.hh b/fem/fem_template.hh index 3e70f00e3..5d38a540b 100644 --- a/fem/fem_template.hh +++ b/fem/fem_template.hh @@ -1,197 +1,199 @@ /** * @file fem_template.hh * @author Guillaume Anciaux * @date Thu Feb 10 10:55:21 2011 * * @brief templated class that calls integration and shape objects * * @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 . * */ #ifndef __AKANTU_FEM_TEMPLATE_HH__ #define __AKANTU_FEM_TEMPLATE_HH__ /* -------------------------------------------------------------------------- */ #include "fem.hh" #include "integrator.hh" #include "shape_functions.hh" #include "shape_lagrange.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ template class FEMTemplate : public FEM{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: FEMTemplate(Mesh & mesh, UInt spatial_dimension = 0, FEMID id = "fem", MemoryID memory_id = 0); virtual ~FEMTemplate(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre-compute all the shape functions, their derivatives and the jacobians - void initShapeFunctions(GhostType ghost_type = _not_ghost); + void initShapeFunctions(const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Integration method bridges */ /* ------------------------------------------------------------------------ */ /// integrate f for all elements of type "type" void integrate(const Vector & f, Vector &intf, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// integrate a scalar value on all elements of type "type" Real integrate(const Vector & f, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// get the number of quadrature points - UInt getNbQuadraturePoints(const ElementType & type); + UInt getNbQuadraturePoints(const ElementType & type, + const GhostType & ghost_type = _not_ghost); /// get shapes precomputed - const Vector & getShapes(const ElementType & type, - const GhostType & ghost_type); + const Vector & getShapes(const ElementType & type, + const GhostType & ghost_type = _not_ghost); /// get the derivatives of shapes const Vector & getShapesDerivatives(const ElementType & type, - const GhostType & ghost_type); + const GhostType & ghost_type = _not_ghost); /// get quadrature points - const Vector & getQuadraturePoints(const ElementType & type); + const Vector & getQuadraturePoints(const ElementType & type, + const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Shape method bridges */ /* ------------------------------------------------------------------------ */ void gradientOnQuadraturePoints(const Vector &u, Vector &nablauq, const UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL); void interpolateOnQuadraturePoints(const Vector &u, Vector &uq, UInt nb_degre_of_freedom, const ElementType & type, - GhostType ghost_type = _not_ghost, + const GhostType & ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /* ------------------------------------------------------------------------ */ /* Other methods */ /* ------------------------------------------------------------------------ */ /// pre-compute normals on control points - void computeNormalsOnControlPoints(GhostType ghost_type = _not_ghost); + void computeNormalsOnControlPoints(const GhostType & ghost_type = _not_ghost); /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const{}; void assembleFieldLumped(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, ElementType type, - GhostType ghost_type); + const GhostType & ghost_type = _not_ghost); void assembleFieldMatrix(const Vector & field, UInt nb_degree_of_freedom, SparseMatrix & matrix, ElementType type, - GhostType ghost_type); + const GhostType & ghost_type = _not_ghost); private: template void assembleLumpedTemplate(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type); + const GhostType & ghost_type); template void assembleLumpedRowSum(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, const Vector & equation_number, - GhostType ghost_type); + const GhostType & ghost_type); template void assembleLumpedDiagonalScaling(const Vector & field_1, UInt nb_degree_of_freedom, Vector & lumped, - const Vector & equation_number, - GhostType ghost_type); + const Vector & equation_number, + const GhostType & ghost_type); template void assembleFieldMatrix(const Vector & field, UInt nb_degree_of_freedom, SparseMatrix & matrix, - GhostType ghost_type); + const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: Integ integrator; Shape shape_functions; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "fem_template_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const FEMTemplate & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_FEM_TEMPLATE_HH__ */ diff --git a/fem/integrator.hh b/fem/integrator.hh index af598267d..129934272 100644 --- a/fem/integrator.hh +++ b/fem/integrator.hh @@ -1,108 +1,102 @@ /** * @file integrator.hh * @author Guillaume Anciaux * @date Thu Feb 10 11:09:12 2011 * * @brief interface for integrator classes * * @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 . * */ #ifndef __AKANTU_INTEGRATOR_HH__ #define __AKANTU_INTEGRATOR_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class Integrator : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Integrator(Mesh & m, IntegratorID myid="integrator"){ mesh = &m; id = myid; }; virtual ~Integrator(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: template inline void precomputeJacobiansOnQuadraturePoints(__attribute__ ((unused)) GhostType ghost_type){} void integrateOnElement(__attribute__ ((unused)) const Vector & f, __attribute__ ((unused)) Real * intf, __attribute__ ((unused)) UInt nb_degre_of_freedom, __attribute__ ((unused)) const Element & elem, __attribute__ ((unused)) GhostType ghost_type) const {}; /// function to print the contain of the class // virtual void printself(std::ostream & stream, int indent = 0) const{}; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: - Mesh * mesh; IntegratorID id; - /// jacobians for all elements ByElementTypeReal jacobians; - - /// jacobians for all elements - ByElementTypeReal ghost_jacobians; - }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "integrator_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const Integrator & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_INTEGRATOR_HH__ */ diff --git a/fem/integrator_gauss.cc b/fem/integrator_gauss.cc index f84514418..8ad31f982 100644 --- a/fem/integrator_gauss.cc +++ b/fem/integrator_gauss.cc @@ -1,269 +1,252 @@ /** * @file integrator_gauss.cc * @author Guillaume Anciaux * @author Nicolas Richart * @date Thu Feb 10 16:52:07 2011 * * @brief implementation of gauss integrator class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "integrator_gauss.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ IntegratorGauss::IntegratorGauss(Mesh & mesh, IntegratorID id) : Integrator(mesh,id){ - for(UInt t = _not_defined; t < _max_element_type; ++t) { - this->jacobians[t] = NULL; - this->ghost_jacobians[t] = NULL; - quadrature_points[t] = NULL; - } + AKANTU_DEBUG_IN(); + + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template -void IntegratorGauss::checkJacobians(GhostType ghost_type) { +void IntegratorGauss::checkJacobians(GhostType ghost_type) const { AKANTU_DEBUG_IN(); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * elem_val; UInt nb_element; - Real * jacobians_val; + elem_val = mesh->getConnectivity(type,ghost_type).values; nb_element = mesh->getConnectivity(type,ghost_type).getSize(); - if(ghost_type == _not_ghost) { - jacobians_val = jacobians[type]->values; - } else { - jacobians_val = ghost_jacobians[type]->values; - } - + Real * jacobians_val = jacobians(type, ghost_type)->values; + for (UInt i = 0; i < nb_element*nb_quadrature_points; ++i,++jacobians_val){ AKANTU_DEBUG_ASSERT(*jacobians_val >0, "Negative jacobian computed," << " possible problem in the element node order"); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::precomputeJacobiansOnQuadraturePoints(GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh->getSpatialDimension(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); Real * weights = ElementClass::getGaussIntegrationWeights(); UInt * elem_val = mesh->getConnectivity(type,ghost_type).values;; UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize(); - std::string ghost = ""; + std::string ghost = ""; if(ghost_type == _ghost) { ghost = "ghost_"; } std::stringstream sstr_jacobians; sstr_jacobians << id << ":" << ghost << "jacobians:" << type; Vector * jacobians_tmp = &(alloc(sstr_jacobians.str(), nb_element*nb_quadrature_points, 1)); Real * jacobians_val = jacobians_tmp->values; Real local_coord[spatial_dimension * nb_nodes_per_element]; for (UInt elem = 0; elem < nb_element; ++elem) { mesh->extractNodalCoordinatesFromElement(local_coord, elem_val+elem*nb_nodes_per_element, nb_nodes_per_element); computeJacobianOnQuadPointsByElement(spatial_dimension, local_coord, nb_nodes_per_element, jacobians_val); for (UInt q = 0; q < nb_quadrature_points; ++q) { *jacobians_val++ *= weights[q]; } // jacobians_val += nb_quadrature_points; } - if(ghost_type == _not_ghost) jacobians[type] = jacobians_tmp; - else ghost_jacobians[type] = jacobians_tmp; + + jacobians(type, ghost_type) = jacobians_tmp; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void IntegratorGauss::integrate(const Vector & in_f, Vector &intf, UInt nb_degre_of_freedom, GhostType ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); - Vector * jac_loc; UInt nb_element = mesh->getNbElement(type,ghost_type); - - if(ghost_type == _not_ghost) { - jac_loc = jacobians[type]; - } else { - jac_loc = ghost_jacobians[type]; - } + Vector * jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_f.getSize() == nb_element * nb_quadrature_points, "The vector in_f(" << in_f.getID() << " size " << in_f.getSize() << ") has not the good size (" << nb_element << ")."); AKANTU_DEBUG_ASSERT(in_f.getNbComponent() == nb_degre_of_freedom , "The vector in_f(" << in_f.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(intf.getNbComponent() == nb_degre_of_freedom, "The vector intf(" << intf.getID() << ") has not the good number of component."); intf.resize(nb_element); Real * in_f_val = in_f.values; Real * intf_val = intf.values; Real * jac_val = jac_loc->values; UInt offset_in_f = in_f.getNbComponent()*nb_quadrature_points; UInt offset_intf = intf.getNbComponent(); Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } integrate(in_f_val, jac, intf_val, nb_degre_of_freedom, nb_quadrature_points); in_f_val += offset_in_f; intf_val += offset_intf; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template Real IntegratorGauss::integrate(const Vector & in_f, GhostType ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); - Vector * jac_loc; - UInt nb_element = mesh->getNbElement(type,ghost_type); - if(ghost_type == _not_ghost) { - jac_loc = jacobians[type]; - } else { - jac_loc = ghost_jacobians[type]; - } + UInt nb_element = mesh->getNbElement(type, ghost_type); + Vector * jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_f.getSize() == nb_element * nb_quadrature_points, "The vector in_f(" << in_f.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_f.getNbComponent() == 1, "The vector in_f(" << in_f.getID() << ") has not the good number of component."); Real intf = 0.; Real * in_f_val = in_f.values; Real * jac_val = jac_loc->values; UInt offset_in_f = in_f.getNbComponent() * nb_quadrature_points; Real * jac = jac_val; for (UInt el = 0; el < nb_element; ++el) { if(filter_elements != NULL) { jac = jac_val + filter_elem_val[el] * nb_quadrature_points; } Real el_intf = 0; integrate(in_f_val, jac, &el_intf, 1, nb_quadrature_points); intf += el_intf; in_f_val += offset_in_f; if(filter_elements == NULL) { jac += nb_quadrature_points; } } AKANTU_DEBUG_OUT(); return intf; } /* -------------------------------------------------------------------------- */ /* template instanciation */ /* -------------------------------------------------------------------------- */ #define INSTANCIATE_TEMPLATE_CLASS(type) \ template void IntegratorGauss:: \ precomputeJacobiansOnQuadraturePoints(GhostType ghost_type); \ template void IntegratorGauss:: \ - checkJacobians(GhostType ghost_type); \ + checkJacobians(GhostType ghost_type) const; \ template void IntegratorGauss:: \ integrate(const Vector & in_f, \ Vector &intf, \ UInt nb_degre_of_freedom, \ GhostType ghost_type, \ const Vector * filter_elements) const; \ template Real IntegratorGauss:: \ integrate(const Vector & in_f, \ GhostType ghost_type, \ const Vector * filter_elements) const; AKANTU_BOOST_ELEMENT_LIST(INSTANCIATE_TEMPLATE_CLASS) #undef INSTANCIATE_TEMPLATE_CLASS __END_AKANTU__ diff --git a/fem/integrator_gauss.hh b/fem/integrator_gauss.hh index 6968ba00f..0cf849c53 100644 --- a/fem/integrator_gauss.hh +++ b/fem/integrator_gauss.hh @@ -1,125 +1,124 @@ /** * @file integrator_gauss.hh * @author Guillaume Anciaux * @author Nicolas Richart * @date Thu Feb 10 16:42:34 2011 * * @brief Gauss integration facilities * * @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 . * */ #ifndef __AKANTU_INTEGRATOR_GAUSS_HH__ #define __AKANTU_INTEGRATOR_GAUSS_HH__ /* -------------------------------------------------------------------------- */ #include "integrator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class IntegratorGauss : public Integrator { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: IntegratorGauss(Mesh & mesh, IntegratorID id="IntegratorGauss"); virtual ~IntegratorGauss(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// precompute jacobians on elements of type "type" template void precomputeJacobiansOnQuadraturePoints(GhostType ghost_type); /// integrate f on the element "elem" of type "type" template inline void integrateOnElement(const Vector & f, Real * intf, UInt nb_degre_of_freedom, const UInt elem, GhostType ghost_type) const; /// integrate f for all elements of type "type" template void integrate(const Vector & in_f, Vector &intf, UInt nb_degre_of_freedom, GhostType ghost_type, const Vector * filter_elements) const; /// integrate scalar field in_f template Real integrate(const Vector & in_f, GhostType ghost_type, const Vector * filter_elements) const; /// return a vector with quadrature points natural coordinates - template Vector & getQuadraturePoints() const; + template Vector & getQuadraturePoints(const GhostType & ghost_type) const; /// compute the vector of quadrature points natural coordinates - template void computeQuadraturePoints(); + template void computeQuadraturePoints(const GhostType & ghost_type); /// check that the jacobians are not negative - template void checkJacobians(GhostType ghost_type); + template void checkJacobians(GhostType ghost_type) const; protected: - + /// compute the jacobians on quad points for a given element - template + template void computeJacobianOnQuadPointsByElement(UInt spatial_dimension, Real * node_coords, UInt nb_nodes_per_element, Real * jacobians); - + /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ private: public: /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: inline void integrate(Real *f, Real *jac, Real * inte, UInt nb_degre_of_freedom, UInt nb_quadrature_points) const; ByElementTypeReal quadrature_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "integrator_gauss_inline_impl.cc" __END_AKANTU__ #endif /* __AKANTU_INTEGRATOR_GAUSS_HH__ */ - diff --git a/fem/integrator_gauss_inline_impl.cc b/fem/integrator_gauss_inline_impl.cc index 7b1317bb4..68cf7b4e2 100644 --- a/fem/integrator_gauss_inline_impl.cc +++ b/fem/integrator_gauss_inline_impl.cc @@ -1,123 +1,125 @@ /** * @file integrator_gauss_inline_impl.cc * @author Guillaume Anciaux * @author Nicolas Richart * @date Thu Feb 10 20:43:52 2011 * * @brief inline function of gauss integrator * * @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 void IntegratorGauss::integrateOnElement(const Vector & f, Real * intf, UInt nb_degre_of_freedom, const UInt elem, GhostType ghost_type) const { - Vector * jac_loc; - - if(ghost_type == _not_ghost) jac_loc = jacobians[type]; - else jac_loc = ghost_jacobians[type]; + Vector * jac_loc = jacobians(type, ghost_type); UInt nb_quadrature_points = ElementClass::getNbQuadraturePoints(); AKANTU_DEBUG_ASSERT(f.getNbComponent() == nb_degre_of_freedom , "The vector f do not have the good number of component."); Real * f_val = f.values + elem * f.getNbComponent(); Real * jac_val = jac_loc->values + elem * nb_quadrature_points; integrate(f_val, jac_val, intf, nb_degre_of_freedom, nb_quadrature_points); } /* -------------------------------------------------------------------------- */ inline void IntegratorGauss::integrate(Real *f, Real *jac, Real * inte, UInt nb_degre_of_freedom, UInt nb_quadrature_points) const { memset(inte, 0, nb_degre_of_freedom * sizeof(Real)); Real *cjac = jac; for (UInt q = 0; q < nb_quadrature_points; ++q) { for (UInt dof = 0; dof < nb_degre_of_freedom; ++dof) { inte[dof] += *f * *cjac; ++f; } ++cjac; } } /* -------------------------------------------------------------------------- */ template -inline Vector & IntegratorGauss::getQuadraturePoints() const { - AKANTU_DEBUG_ASSERT(quadrature_points[type] != NULL, - "quadrature points for type " << type - << " have not been initialized." +inline Vector & IntegratorGauss::getQuadraturePoints(const GhostType & ghost_type) const { + AKANTU_DEBUG_ASSERT(quadrature_points.exists(type, ghost_type), + "Quadrature points for type " + << quadrature_points.printType(type, ghost_type) + << " have not been initialized." << " Did you use 'computeQuadraturePoints' function ?"); - return *quadrature_points[type]; + return *quadrature_points(type, ghost_type); } /* -------------------------------------------------------------------------- */ template -inline void IntegratorGauss::computeQuadraturePoints() { +inline void IntegratorGauss::computeQuadraturePoints(const GhostType & ghost_type) { UInt n_coords = ElementClass::getNbQuadraturePoints(); UInt dim = ElementClass::getSpatialDimension(); - if (quadrature_points[type] == NULL){ - std::stringstream sstr; sstr << id << ":quadrature_points:" << type; - quadrature_points[type] = &(alloc(sstr.str(), 0, dim, REAL_INIT_VALUE)); + std::string ghost = ""; + if(ghost_type == _ghost) { + ghost = "ghost_"; + } + + if (!quadrature_points.exists(type, ghost_type)){ + std::stringstream sstr; sstr << id << ":" << ghost << "quadrature_points:" << type; + quadrature_points(type, ghost_type) = &(alloc(sstr.str(), 0, dim, REAL_INIT_VALUE)); } - else quadrature_points[type]->resize(0); + else quadrature_points(type, ghost_type)->resize(0); Real * coord_val = ElementClass::getQuadraturePoints(); for (UInt i = 0; i < n_coords; ++i) { - quadrature_points[type]->push_back(coord_val); + quadrature_points(type, ghost_type)->push_back(coord_val); coord_val += dim; } } /* -------------------------------------------------------------------------- */ template inline void IntegratorGauss:: computeJacobianOnQuadPointsByElement(UInt spatial_dimension, Real * node_coords, UInt nb_nodes_per_element, Real * jacobians) { - + Real * quad = ElementClass::getQuadraturePoints(); const UInt nb_quad_points = ElementClass::getNbQuadraturePoints(); // compute dnds Real dnds[nb_nodes_per_element * spatial_dimension * nb_quad_points]; - ElementClass::computeDNDS(quad, + ElementClass::computeDNDS(quad, nb_quad_points, dnds); // compute dxds const UInt element_dimension = ElementClass::getSpatialDimension(); Real dxds[element_dimension * spatial_dimension * nb_quad_points]; - ElementClass::computeDXDS(dnds, nb_quad_points, + ElementClass::computeDXDS(dnds, nb_quad_points, node_coords, spatial_dimension, dxds); // jacobian - ElementClass::computeJacobian(dxds, nb_quad_points, + ElementClass::computeJacobian(dxds, nb_quad_points, spatial_dimension, jacobians); } /* -------------------------------------------------------------------------- */ - diff --git a/fem/mesh.cc b/fem/mesh.cc index 2a66de182..de02633a5 100644 --- a/fem/mesh.cc +++ b/fem/mesh.cc @@ -1,277 +1,239 @@ /** * @file mesh.cc * @author Nicolas Richart * @date Wed Jun 16 12:02:26 2010 * * @brief class handling meshes * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "mesh.hh" #include "element_class.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ const Element ElementNull(_not_defined, 0); /* -------------------------------------------------------------------------- */ void Element::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Element [" << type << ", " << element << "]"; } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL), created_nodes(true), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), - types_offsets(Vector(_max_element_type + 1, 1)), - ghost_types_offsets(Vector(_max_element_type + 1, 1)), + types_offsets(Vector((UInt) _max_element_type + 1, 1)), + ghost_types_offsets(Vector((UInt) _max_element_type + 1, 1)), nb_surfaces(0) { AKANTU_DEBUG_IN(); std::stringstream sstr; sstr << id << ":coordinates"; this->nodes = &(alloc(sstr.str(), 0, this->spatial_dimension)); nb_global_nodes = 0; init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, const VectorID & nodes_id, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL), created_nodes(false), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), - types_offsets(Vector(_max_element_type + 1, 1)), - ghost_types_offsets(Vector(_max_element_type + 1, 1)) { + types_offsets(Vector((UInt) _max_element_type + 1, 1)), + ghost_types_offsets(Vector((UInt) _max_element_type + 1, 1)) { AKANTU_DEBUG_IN(); this->nodes = &(getVector(nodes_id)); nb_global_nodes = nodes->getSize(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Mesh::Mesh(UInt spatial_dimension, Vector & nodes, const MeshID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), nodes_global_ids(NULL), nodes_type(NULL), created_nodes(false), spatial_dimension(spatial_dimension), internal_facets_mesh(NULL), types_offsets(Vector(_max_element_type + 1, 1)), ghost_types_offsets(Vector(_max_element_type + 1, 1)) { AKANTU_DEBUG_IN(); this->nodes = &(nodes); nb_global_nodes = nodes.getSize(); init(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::init() { - for(UInt t = _not_defined; t < _max_element_type; ++t) { - connectivities[t] = NULL; - ghost_connectivities[t] = NULL; - surface_id[t] = NULL; - //reversed_elements_pbc[t] = NULL; - uint_data[t].clear(); - ghost_uint_data[t].clear(); - } - - this->types_offsets.resize(_max_element_type); + // this->types_offsets.resize(_max_element_type); nodes_type = NULL; computeBoundingBox(); } /* -------------------------------------------------------------------------- */ Mesh::~Mesh() { AKANTU_DEBUG_IN(); - for (UInt t = _not_defined; t < _max_element_type; ++t) { - if(uint_data[t].size() > 0) { - UIntDataMap::iterator it; - for (it = uint_data[t].begin(); it != uint_data[t].end(); ++it) { - if(it->second) delete it->second; - } - uint_data[t].clear(); - } - if(ghost_uint_data[t].size() > 0) { - UIntDataMap::iterator it; - for (it = ghost_uint_data[t].begin(); it != ghost_uint_data[t].end(); ++it) { - if(it->second) delete it->second; + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + + const ConnectivityTypeList & type_list = getConnectivityTypeList(gt); + ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + UIntDataMap & map = uint_data(*it, gt); + UIntDataMap::iterator dit; + for (dit = map.begin(); dit != map.end(); ++dit) { + if(dit->second) delete dit->second; } - ghost_uint_data[t].clear(); + map.clear(); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Mesh::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Mesh [" << std::endl; stream << space << " + id : " << this->id << std::endl; stream << space << " + spatial dimension : " << this->spatial_dimension << std::endl; stream << space << " + nodes [" << std::endl; nodes->printself(stream, indent+2); stream << space << " ]" << std::endl; - ConnectivityTypeList::const_iterator it; - for(it = type_set.begin(); it != type_set.end(); ++it) { - stream << space << " + connectivities ("<< *it <<") [" << std::endl; - (connectivities[*it])->printself(stream, indent+2); - stream << space << " ]" << std::endl; - } - for(it = ghost_type_set.begin(); it != ghost_type_set.end(); ++it) { - stream << space << " + ghost_connectivities ("<< *it <<") [" << std::endl; - (ghost_connectivities[*it])->printself(stream, indent+2); - stream << space << " ]" << std::endl; - } + stream << space << " + connectivities [" << std::endl; + connectivities.printself(stream, indent+2); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ void Mesh::computeBoundingBox(){ AKANTU_DEBUG_IN(); UInt dim = spatial_dimension; for (UInt k = 0; k < dim; ++k) { xmin[k] = std::numeric_limits::max(); xmax[k] = std::numeric_limits::min(); } Real * coords = nodes->values; for (UInt i = 0; i < nodes->getSize(); ++i) { for (UInt k = 0; k < dim; ++k) { xmin[k] = std::min(xmin[k],coords[dim*i+k]); xmax[k] = std::max(xmax[k],coords[dim*i+k]); } } - - StaticCommunicator * comm = + + StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); - + comm->allReduce(xmin,dim,_so_min); comm->allReduce(xmax,dim,_so_max); - for (UInt k = 0; k < dim; ++k) + for (UInt k = 0; k < dim; ++k) size[k] = xmax[k] - xmin[k]; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Mesh::initByElementTypeRealVector(ByElementTypeReal & vect, - UInt nb_component, - UInt dim, - const std::string & obj_id, - const std::string & vect_id, - GhostType ghost_type) { +template +void Mesh::initByElementTypeVector(ByElementTypeVector & vect, + UInt nb_component, + UInt dim, + const std::string & obj_id, + const std::string & vect_id) { AKANTU_DEBUG_IN(); - for(UInt t = _not_defined; t < _max_element_type; ++t) - vect[t] = NULL; - - std::string ghost_id = ""; - - if (ghost_type == _ghost) { - ghost_id = "ghost_"; - } - - const Mesh::ConnectivityTypeList & type_list = getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(dim > 0 && Mesh::getSpatialDimension(*it) != dim) continue; - std::stringstream sstr; sstr << obj_id << ":" << ghost_id << vect_id << ":" << *it; - if (vect[*it] == NULL){ - vect[*it] = &(alloc(sstr.str(), 0, - nb_component, REAL_INIT_VALUE)); - } - } - - AKANTU_DEBUG_OUT(); -} + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; -/* -------------------------------------------------------------------------- */ -void Mesh::initByElementTypeUIntVector(ByElementTypeUInt & vect, - UInt nb_component, - UInt dim, - const std::string & obj_id, - const std::string & vect_id, - GhostType ghost_type) { - AKANTU_DEBUG_IN(); + std::string ghost_id = ""; + if (gt == _ghost) ghost_id = "ghost_"; - for(UInt t = _not_defined; t < _max_element_type; ++t) - vect[t] = NULL; + const Mesh::ConnectivityTypeList & type_list = getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + if(dim > 0 && Mesh::getSpatialDimension(*it) != dim) continue; - std::string ghost_id = ""; - - if (ghost_type == _ghost) { - ghost_id = "ghost_"; - } + std::stringstream sstr; sstr << obj_id << ":" << ghost_id << vect_id << ":" << *it; - const Mesh::ConnectivityTypeList & type_list = getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(dim > 0 && Mesh::getSpatialDimension(*it) != dim) continue; - std::stringstream sstr; sstr << obj_id << ":" << ghost_id << vect_id << ":" << *it; - if (vect[*it] == NULL){ - vect[*it] = &(alloc(sstr.str(), 0, - nb_component, UINT_INIT_VALUE)); + AKANTU_DEBUG_ASSERT(!vect.exists(*it, gt), "Error initializing the ByElementType object, " + << obj_id << " " << vect.printType(*it, gt) << " already exists."); + vect(*it, gt) = &(alloc(sstr.str(), 0, + nb_component, REAL_INIT_VALUE)); } } AKANTU_DEBUG_OUT(); } - - +/* -------------------------------------------------------------------------- */ +template void Mesh::initByElementTypeVector(ByElementTypeVector & vect, + UInt nb_component, + UInt dim, + const std::string & obj_id, + const std::string & vect_id); +template void Mesh::initByElementTypeVector(ByElementTypeVector & vect, + UInt nb_component, + UInt dim, + const std::string & obj_id, + const std::string & vect_id); +template void Mesh::initByElementTypeVector(ByElementTypeVector & vect, + UInt nb_component, + UInt dim, + const std::string & obj_id, + const std::string & vect_id); __END_AKANTU__ diff --git a/fem/mesh.hh b/fem/mesh.hh index 2d615182a..e9b80b007 100644 --- a/fem/mesh.hh +++ b/fem/mesh.hh @@ -1,438 +1,460 @@ /** * @file mesh.hh * @author Nicolas Richart * @date Wed Jun 16 11:53:53 2010 * * @brief the class representing the meshes * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_HH__ #define __AKANTU_MESH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "aka_vector.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ + /* -------------------------------------------------------------------------- */ -/// to store data Vector by element type -typedef Vector * ByElementTypeReal[_max_element_type]; +/* ByElementType */ +/* -------------------------------------------------------------------------- */ +template class ByElementType { +private: + typedef std::map DataMap; +public: + ByElementType(); + ~ByElementType(); -/// to store data Vector by element type -typedef Vector * ByElementTypeInt [_max_element_type]; + inline static std::string printType(const ElementType & type, const GhostType & ghost_type); + + inline bool exists(ElementType type, GhostType ghost_type = _not_ghost) const; + + inline const Stored & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; + inline Stored & operator()(const ElementType & type, const GhostType & ghost_type = _not_ghost); + + void printself(std::ostream & stream, int indent = 0) const; + +private: + inline DataMap & getData(GhostType ghost_type); + inline const DataMap & getData(GhostType ghost_type) const; + +/* -------------------------------------------------------------------------- */ +private: + DataMap data; + DataMap ghost_data; +}; + +template +class ByElementTypeVector : public ByElementType *> {}; +/// to store data Vector by element type +typedef ByElementTypeVector ByElementTypeReal; +/// to store data Vector by element type +typedef ByElementTypeVector ByElementTypeInt; /// to store data Vector by element type -typedef Vector * ByElementTypeUInt[_max_element_type]; +typedef ByElementTypeVector ByElementTypeUInt; +/// Map of data of type UInt stored in a mesh +typedef std::map *> UIntDataMap; +typedef ByElementType ByElementTypeUIntDataMap; + +/* -------------------------------------------------------------------------- */ +/* Element */ /* -------------------------------------------------------------------------- */ class Element { public: - Element(ElementType type = _not_defined, UInt element = 0) : - type(type), element(element) {}; + Element(ElementType type = _not_defined, UInt element = 0, GhostType ghost_type = _not_ghost) : + type(type), element(element), ghost_type(ghost_type) {}; Element(const Element & element) { this->type = element.type; this->element = element.element; + this->ghost_type = element.ghost_type; } ~Element() {}; /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; public: ElementType type; UInt element; + GhostType ghost_type; }; extern const Element ElementNull; -/* -------------------------------------------------------------------------- */ /** * @class Mesh this contain the coordinates of the nodes in the Mesh.nodes Vector, * and the connectivity. The connectivity are stored in by element types. * * To know all the element types present in a mesh you can get the Mesh::ConnectivityTypeList * * In order to loop on all element you have to loop on all types like this : * @code const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { UInt nb_element = mesh.getNbElement(*it); UInt * conn = mesh.getConnectivity(*it).values; for(UInt e = 0; e < nb_element; ++e) { ... } } @endcode */ class Mesh : protected Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: /// constructor that create nodes coordinates array Mesh(UInt spatial_dimension, const MeshID & id = "mesh" , const MemoryID & memory_id = 0); /// constructor that use an existing nodes coordinates array, by knowing its ID Mesh(UInt spatial_dimension, const VectorID & nodes_id, const MeshID & id = "mesh", const MemoryID & memory_id = 0); /** * constructor that use an existing nodes coordinates * array, by getting the vector of coordinates */ Mesh(UInt spatial_dimension, Vector & nodes, const MeshID & id = "mesh", const MemoryID & memory_id = 0); virtual ~Mesh(); /// @typedef ConnectivityTypeList list of the types present in a Mesh typedef std::set ConnectivityTypeList; - typedef Vector * NormalsMap[_max_element_type]; + // typedef Vector * NormalsMap[_max_element_type]; private: /// initialize the connectivity to NULL and other stuff void init(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /// function that computes the bounding box (fills xmin, xmax) void computeBoundingBox(); /// init a by-element-type real vector with provided ids - void initByElementTypeRealVector(ByElementTypeReal & v, UInt nb_component, - UInt dimension, - const std::string & obj_id, - const std::string & vec_id, - GhostType ghost_type); - - /// init a by-element-type real vector with provided ids - void initByElementTypeUIntVector(ByElementTypeUInt & v,UInt nb_component, - UInt dimension, - const std::string & obj_id, - const std::string & vec_id, - GhostType ghost_type=_not_ghost); + template + void initByElementTypeVector(ByElementTypeVector & v, + UInt nb_component, UInt size, + const std::string & obj_id, + const std::string & vec_id); /// extract coordinates of nodes from an element inline void extractNodalCoordinatesFromElement(Real * local_coords, UInt * connectivity, UInt n_nodes); /// extract coordinates of nodes from a reversed element inline void extractNodalCoordinatesFromPBCElement(Real * local_coords, UInt * connectivity, UInt n_nodes); /// convert a element to a linearized element inline UInt elementToLinearized(const Element & elem); /// convert a linearized element to an element inline Element linearizedToElement (UInt linearized_element); /// update the types offsets array for the conversions - inline void updateTypesOffsets(); + inline void updateTypesOffsets(GhostType ghost_type); - /// convert a element to a linearized element - inline UInt ghostElementToLinearized(const Element & elem); + // /// convert a element to a linearized element + // inline UInt ghostElementToLinearized(const Element & elem); - /// convert a linearized element to an element - inline Element ghostLinearizedToElement (UInt linearized_element); + // /// convert a linearized element to an element + // inline Element ghostLinearizedToElement (UInt linearized_element); /// update the types offsets array for the conversions - inline void updateGhostTypesOffsets(); + // inline void updateGhostTypesOffsets(); /// add a Vector of connectivity for the type . inline void addConnecticityType(const ElementType & type); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const MeshID &); /// get the spatial dimension of the mesh = number of component of the coordinates AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the nodes Vector aka coordinates AKANTU_GET_MACRO(Nodes, *nodes, const Vector &); /// get the number of nodes AKANTU_GET_MACRO(NbNodes, nodes->getSize(), UInt); /// get the Vector of global ids of the nodes (only used in parallel) AKANTU_GET_MACRO(GlobalNodesIds, *nodes_global_ids, const Vector &); /// get the global id of a node inline UInt getNodeGlobalId(UInt local_id) const; /// get the global number of nodes inline UInt getNbGlobalNodes() const; /// get the nodes type Vector AKANTU_GET_MACRO(NodesType, *nodes_type, const Vector &); inline Int getNodeType(UInt local_id) const; /// say if a node is a pure ghost node inline bool isPureGhostNode(UInt n) const; /// say if a node is pur local or master node inline bool isLocalOrMasterNode(UInt n) const; inline bool isLocalNode(UInt n) const; inline bool isMasterNode(UInt n) const; inline bool isSlaveNode(UInt n) const; AKANTU_GET_MACRO(XMin, xmin[0], Real); AKANTU_GET_MACRO(YMin, xmin[1], Real); AKANTU_GET_MACRO(ZMin, xmin[2], Real); AKANTU_GET_MACRO(XMax, xmax[0], Real); AKANTU_GET_MACRO(YMax, xmax[1], Real); AKANTU_GET_MACRO(ZMax, xmax[2], Real); /// get the number of surfaces AKANTU_GET_MACRO(NbSurfaces, nb_surfaces, UInt); /// get the connectivity Vector for a given type - const Vector & getConnectivity(const ElementType & type, - const GhostType & ghost_type = _not_ghost) const; - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Connectivity, connectivities, const Vector &); - /// get the connecticity of ghost elements of a given type - //AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostConnectivity, ghost_connectivities, const Vector &); - - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Normals, normals, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Connectivity, connectivities, UInt); /// @todo take out this set, if mesh can read surface id /// set the number of surfaces AKANTU_SET_MACRO(NbSurfaces, nb_surfaces, UInt); /// get the number of element of a type in the mesh inline UInt getNbElement(const ElementType & type, const GhostType & ghost_type = _not_ghost) const; // /// get the number of ghost element of a type in the mesh // inline UInt getNbGhostElement(const ElementType & type) const; /// get the connectivity list either for the elements or the ghost elements inline const ConnectivityTypeList & getConnectivityTypeList(GhostType ghost_type = _not_ghost) const; /// get the mesh of the internal facets inline const Mesh & getInternalFacetsMesh() const; /// compute the barycenter of a given element inline void getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type = _not_ghost) const; /// get the surface values of facets - inline const Vector & getSurfaceId(const ElementType & type) const; + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(SurfaceID, surface_id, UInt); /// set the int data to the surface id vectors - inline void setSurfaceIdsFromIntData(std::string & data_name); + inline void setSurfaceIDsFromIntData(std::string & data_name); inline const Vector & getUIntData(const ElementType & el_type, - const std::string & data_name) const; + const std::string & data_name, + const GhostType & ghost_type = _not_ghost) const; /* ------------------------------------------------------------------------ */ /* Wrappers on ElementClass functions */ /* ------------------------------------------------------------------------ */ public: /// get the number of nodes per element for a given element type static inline UInt getNbNodesPerElement(const ElementType & type); /// get the number of nodes per element for a given element type considered as /// a first order element static inline ElementType getP1ElementType(const ElementType & type); /// get spatial dimension of a type of element static inline UInt getSpatialDimension(const ElementType & type); /// get number of facets of a given element type static inline UInt getNbFacetsPerElement(const ElementType & type); /// get number of facets of a given element type static inline UInt ** getFacetLocalConnectivity(const ElementType & type); /// get the type of the surface element associated to a given element static inline ElementType getFacetElementType(const ElementType & type); /// get the pointer to the list of elements for a given type inline Vector * getReversedElementsPBCPointer(const ElementType & type); + /* ------------------------------------------------------------------------ */ + /* Private methods for friends */ + /* ------------------------------------------------------------------------ */ private: friend class MeshIOMSH; friend class MeshIODiana; friend class MeshUtils; friend class DistributedSynchronizer; AKANTU_GET_MACRO(NodesPointer, nodes, Vector *); /// get a pointer to the nodes_global_ids Vector and create it if necessary inline Vector * getNodesGlobalIdsPointer(); /// get a pointer to the nodes_type Vector and create it if necessary inline Vector * getNodesTypePointer(); /// get a pointer to the connectivity Vector for the given type and create it if necessary inline Vector * getConnectivityPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); /// get a pointer to the internal_facets Mesh and create it if necessary inline Mesh * getInternalFacetsMeshPointer(); // inline Vector * getNormalsPointer(ElementType type) const; /// get a pointer to the surface_id Vector for the given type and create it if necessary - inline Vector * getSurfaceIdPointer(const ElementType & type); + inline Vector * getSurfaceIDPointer(const ElementType & type, const GhostType & ghost_type = _not_ghost); - typedef std::map * > UIntDataMap; - typedef UIntDataMap ByElementTypeUIntDataMap[_max_element_type]; - /// get the IntDataMap for a given ElementType + /// get the UIntDataMap for a given ElementType inline UIntDataMap & getUIntDataMap(const ElementType & el_type, const GhostType & ghost_type = _not_ghost); /// get the IntDataMap pointer (moidifyable) for a given ElementType - inline Vector * getUIntDataPointer(const ElementType & el_type, const std::string & data_name); + inline Vector * getUIntDataPointer(const ElementType & el_type, + const std::string & data_name, + const GhostType & ghost_type = _not_ghost); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// id of the mesh MeshID id; /// array of the nodes coordinates Vector * nodes; /// global node ids Vector * nodes_global_ids; /// node type, -3 pure ghost, -2 master for the node, -1 normal node, i in /// [0-N] slave node and master is proc i Vector * nodes_type; /// global number of nodes; UInt nb_global_nodes; /// boolean to know if the nodes have to be deleted with the mesh or not bool created_nodes; /// all class of elements present in this mesh (for heterogenous meshes) ByElementTypeUInt connectivities; /// map to normals for all class of elements present in this mesh ByElementTypeReal normals; /// list of all existing types in the mesh ConnectivityTypeList type_set; /// the spatial dimension of this mesh UInt spatial_dimension; /// internal facets mesh Mesh * internal_facets_mesh; /// types offsets Vector types_offsets; - /// all class of elements present in this mesh (for heterogenous meshes) - ByElementTypeUInt ghost_connectivities; - /// list of all existing types in the mesh ConnectivityTypeList ghost_type_set; - /// ghost types offsets Vector ghost_types_offsets; /// number of surfaces present in this mesh UInt nb_surfaces; /// surface id of the surface elements in this mesh ByElementTypeUInt surface_id; - ByElementTypeUInt ghost_surface_id; /// min of coordinates Real xmin[3]; /// max of coordinates Real xmax[3]; /// size covered by the mesh on each direction Real size[3]; // /// list of elements that are reversed due to pbc // ByElementTypeUInt reversed_elements_pbc; // /// direction in which pbc are to be applied // UInt pbc_directions[3]; /// list of the vectors corresponding to tags in the mesh ByElementTypeUIntDataMap uint_data; - ByElementTypeUIntDataMap ghost_uint_data; }; /* -------------------------------------------------------------------------- */ /* Inline functions */ /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Element & _this) { _this.printself(stream); return stream; } #include "mesh_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Mesh & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MESH_HH__ */ diff --git a/fem/mesh_inline_impl.cc b/fem/mesh_inline_impl.cc index e4585c33d..72a01e4e7 100644 --- a/fem/mesh_inline_impl.cc +++ b/fem/mesh_inline_impl.cc @@ -1,592 +1,641 @@ /** * @file mesh_inline_impl.cc * @author Nicolas Richart * @date Wed Jul 14 23:58:08 2010 * * @brief Implementation of the inline functions of the mesh class * * @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 . * */ /* -------------------------------------------------------------------------- */ inline UInt Mesh::elementToLinearized(const Element & elem) { AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && elem.element < types_offsets.values[elem.type+1], "The element " << elem << "does not exists in the mesh " << id); return types_offsets.values[elem.type] + elem.element; } /* -------------------------------------------------------------------------- */ inline Element Mesh::linearizedToElement (UInt linearized_element) { UInt t; for (t = _not_defined + 1; linearized_element > types_offsets.values[t] && t <= _max_element_type; ++t); AKANTU_DEBUG_ASSERT(t < _max_element_type, "The linearized element " << linearized_element << "does not exists in the mesh " << id); return Element((ElementType) t, linearized_element-types_offsets.values[t]); } /* -------------------------------------------------------------------------- */ -inline void Mesh::updateTypesOffsets() { - UInt count = 0; - for (UInt t = _not_defined; t <= _max_element_type; ++t) { - types_offsets.values[t] = count; - count += (t == _max_element_type || connectivities[t] == NULL) ? - 0 : connectivities[t]->getSize(); - } -} - -/* -------------------------------------------------------------------------- */ -inline UInt Mesh::ghostElementToLinearized(const Element & elem) { - AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && - elem.element < ghost_types_offsets.values[elem.type+1], - "The ghost element " << elem - << "does not exists in the mesh " << id); +inline void Mesh::updateTypesOffsets(GhostType ghost_type) { + types_offsets.clear(); + ConnectivityTypeList::const_iterator it; + for (it = type_set.begin(); it != type_set.end(); ++it) + types_offsets(*it) = connectivities(*it, ghost_type)->getSize(); - return ghost_types_offsets.values[elem.type] + - elem.element + - types_offsets.values[_max_element_type]; + for (UInt t = _not_defined + 1; t <= _max_element_type; ++t) + types_offsets(t) += types_offsets(t - 1); } -/* -------------------------------------------------------------------------- */ -inline Element Mesh::ghostLinearizedToElement (UInt linearized_element) { - AKANTU_DEBUG_ASSERT(linearized_element >= types_offsets.values[_max_element_type], - "The linearized element " << linearized_element - << "is not a ghost element in the mesh " << id); +// /* -------------------------------------------------------------------------- */ +// inline UInt Mesh::ghostElementToLinearized(const Element & elem) { +// AKANTU_DEBUG_ASSERT(elem.type < _max_element_type && +// elem.element < ghost_types_offsets.values[elem.type+1], +// "The ghost element " << elem +// << "does not exists in the mesh " << id); + +// return ghost_types_offsets.values[elem.type] + +// elem.element + +// types_offsets.values[_max_element_type]; +// } +// /* -------------------------------------------------------------------------- */ +// inline Element Mesh::ghostLinearizedToElement (UInt linearized_element) { +// AKANTU_DEBUG_ASSERT(linearized_element >= types_offsets.values[_max_element_type], +// "The linearized element " << linearized_element +// << "is not a ghost element in the mesh " << id); - linearized_element -= types_offsets.values[_max_element_type]; - UInt t; - for (t = _not_defined + 1; - linearized_element > ghost_types_offsets.values[t] && t <= _max_element_type; ++t); - AKANTU_DEBUG_ASSERT(t < _max_element_type, - "The ghost linearized element " << linearized_element - << "does not exists in the mesh " << id); +// linearized_element -= types_offsets.values[_max_element_type]; +// UInt t; +// for (t = _not_defined + 1; +// linearized_element > ghost_types_offsets.values[t] && t <= _max_element_type; ++t); - t--; - return Element((ElementType) t, linearized_element - ghost_types_offsets.values[t]); -} +// AKANTU_DEBUG_ASSERT(t < _max_element_type, +// "The ghost linearized element " << linearized_element +// << "does not exists in the mesh " << id); -/* -------------------------------------------------------------------------- */ -inline void Mesh::updateGhostTypesOffsets() { - UInt count = 0; - for (UInt t = _not_defined; t <= _max_element_type; ++t) { - ghost_types_offsets.values[t] = count; - count += (t == _max_element_type || ghost_connectivities[t] == NULL) ? - 0 : ghost_connectivities[t]->getSize(); - } -} +// t--; +// return Element((ElementType) t, linearized_element - ghost_types_offsets.values[t]); +// } + +// /* -------------------------------------------------------------------------- */ +// inline void Mesh::updateGhostTypesOffsets() { +// ghost_types_offsets.clear(); +// ByElementTypeUInt::const_iterator it; +// for (it = ghost_connectivities.begin(); it != ghost_connectivities.end(); ++it) +// ghost_types_offsets(it->first) = it->second->getSize(); + +// for (UInt t = _not_defined + 1; t <= _max_element_type; ++t) +// ghost_types_offsets(t) += ghost_types_offsets(t - 1); +// } /* -------------------------------------------------------------------------- */ inline const Mesh::ConnectivityTypeList & Mesh::getConnectivityTypeList(GhostType ghost_type) const { if(ghost_type == _not_ghost) return type_set; else return ghost_type_set; } /* -------------------------------------------------------------------------- */ inline Vector * Mesh::getNodesGlobalIdsPointer() { AKANTU_DEBUG_IN(); if(nodes_global_ids == NULL) { std::stringstream sstr; sstr << id << ":nodes_global_ids"; nodes_global_ids = &(alloc(sstr.str(), nodes->getSize(), 1)); } AKANTU_DEBUG_OUT(); return nodes_global_ids; } /* -------------------------------------------------------------------------- */ inline Vector * Mesh::getNodesTypePointer() { AKANTU_DEBUG_IN(); if(nodes_type == NULL) { std::stringstream sstr; sstr << id << ":nodes_type"; nodes_type = &(alloc(sstr.str(), nodes->getSize(), 1, -1)); } AKANTU_DEBUG_OUT(); return nodes_type; } /* -------------------------------------------------------------------------- */ inline Vector * Mesh::getConnectivityPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); - Vector ** con = NULL; - if (ghost_type == _not_ghost) con = &connectivities[type]; - else con = &ghost_connectivities[type]; - - if(*con == NULL) { + if(!connectivities.exists(type, ghost_type)) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::stringstream sstr; sstr << id << ":"; if (ghost_type == _ghost) sstr << "ghost_"; sstr << "connectivity:" << type; - *con = &(alloc(sstr.str(), - 0, - nb_nodes_per_element)); + connectivities(type, ghost_type) = &(alloc(sstr.str(), + 0, + nb_nodes_per_element)); AKANTU_DEBUG_INFO("The connectivity vector for the type " << type << " created"); - if (ghost_type == _not_ghost){ - type_set.insert(type); - updateTypesOffsets(); - } - else { - ghost_type_set.insert(type); - updateGhostTypesOffsets(); - } + if (ghost_type == _not_ghost) type_set.insert(type); + else ghost_type_set.insert(type); + + updateTypesOffsets(ghost_type); } AKANTU_DEBUG_OUT(); - return *con; + return connectivities(type, ghost_type); } // /* -------------------------------------------------------------------------- */ // inline Vector * Mesh::getGhostConnectivityPointer(const ElementType & type) { // AKANTU_DEBUG_IN(); // if(ghost_connectivities[type] == NULL) { // UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); // std::stringstream sstr; // sstr << id << ":ghost_connectivity:" << type; // ghost_connectivities[type] = &(alloc(sstr.str(), // 0, // nb_nodes_per_element)); // ghost_type_set.insert(type); // AKANTU_DEBUG_INFO("The connectivity vector for the type " // << type << " created"); // updateGhostTypesOffsets(); // } // AKANTU_DEBUG_OUT(); // return ghost_connectivities[type]; // } /* -------------------------------------------------------------------------- */ inline const Mesh & Mesh::getInternalFacetsMesh() const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); if (!internal_facets_mesh) AKANTU_DEBUG_ERROR("Internal facets mesh was not created before access " << "=> use mesh utils to that purpose"); return *internal_facets_mesh; } /* -------------------------------------------------------------------------- */ inline Mesh * Mesh::getInternalFacetsMeshPointer() { AKANTU_DEBUG_IN(); if (!internal_facets_mesh){ std::stringstream name(this->id); name << ":internalfacets"; internal_facets_mesh = new Mesh(this->spatial_dimension-1,*this->nodes,name.str()); } AKANTU_DEBUG_OUT(); return internal_facets_mesh; } /* -------------------------------------------------------------------------- */ -inline Vector * Mesh::getSurfaceIdPointer(const ElementType & type) { +inline Vector * Mesh::getSurfaceIDPointer(const ElementType & type, const GhostType & ghost_type) { AKANTU_DEBUG_IN(); - if(surface_id[type] == NULL) { + if(!surface_id.exists(type, ghost_type)) { std::stringstream sstr; sstr << id << ":surface_id:" << type; - surface_id[type] = &(alloc(sstr.str(), - 0, - 1)); + surface_id(type, ghost_type) = &(alloc(sstr.str(), + 0, + 1)); AKANTU_DEBUG_INFO("The surface id vector for the type " << type << " created"); } AKANTU_DEBUG_OUT(); - return surface_id[type]; + return surface_id(type, ghost_type); } /* -------------------------------------------------------------------------- */ // inline Vector * Mesh::getReversedElementsPBCPointer(const ElementType & type) { // AKANTU_DEBUG_IN(); - + // if(reversed_elements_pbc[type] == NULL) { // AKANTU_DEBUG_ERROR("There are no reversed elements for the type" << type); // } // AKANTU_DEBUG_OUT(); // return reversed_elements_pbc[type]; // } /* -------------------------------------------------------------------------- */ inline Vector * Mesh::getUIntDataPointer(const ElementType & el_type, - const std::string & data_name) { + const std::string & data_name, + const GhostType & ghost_type) { // AKANTU_DEBUG_IN(); Vector * data; - Mesh::UIntDataMap::iterator it = uint_data[el_type].find(data_name); - if(it == uint_data[el_type].end()) { + UIntDataMap & map = uint_data(el_type, ghost_type); + UIntDataMap::iterator it = map.find(data_name); + if(it == map.end()) { data = new Vector(0, 1, data_name); - uint_data[el_type][data_name] = data; + map[data_name] = data; } else { data = it->second; } // AKANTU_DEBUG_OUT(); return data; } /* -------------------------------------------------------------------------- */ inline const Vector & Mesh::getUIntData(const ElementType & el_type, - const std::string & data_name) const { + const std::string & data_name, + const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); - Mesh::UIntDataMap::const_iterator it = uint_data[el_type].find(data_name); + const UIntDataMap & map = uint_data(el_type, ghost_type); + UIntDataMap::const_iterator it = map.find(data_name); - AKANTU_DEBUG_ASSERT(it != uint_data[el_type].end(), + AKANTU_DEBUG_ASSERT(it != map.end(), "No data named " << data_name << " in the mesh " << id); - + AKANTU_DEBUG_OUT(); return *(it->second); } /* -------------------------------------------------------------------------- */ -inline UInt Mesh::getNbElement(const ElementType & type, +inline UIntDataMap & Mesh::getUIntDataMap(const ElementType & el_type, + const GhostType & ghost_type) { + // AKANTU_DEBUG_ASSERT(uint_data.exists(el_type, ghost_type), + // "No UIntDataMap for the type (" << ghost_type << ":" << el_type << ")"); + return uint_data(el_type, ghost_type); +}; + +/* -------------------------------------------------------------------------- */ +inline UInt Mesh::getNbElement(const ElementType & type, const GhostType & ghost_type) const { AKANTU_DEBUG_IN(); - Vector * con = NULL; - if (ghost_type == _not_ghost) con = connectivities[type]; - else con = ghost_connectivities[type]; - - if (con == NULL) return 0; + const ByElementTypeUInt & const_conn = connectivities; AKANTU_DEBUG_OUT(); - return con->getSize(); + return const_conn(type, ghost_type)->getSize(); } -// /* -------------------------------------------------------------------------- */ -// inline UInt Mesh::getNbGhostElement(const ElementType & type) const { -// AKANTU_DEBUG_IN(); - -// AKANTU_DEBUG_ASSERT(ghost_connectivities[type] != NULL, -// "No element of kind : " << type << " in " << id); - -// AKANTU_DEBUG_OUT(); -// return ghost_connectivities[type]->getSize(); -// } - /* -------------------------------------------------------------------------- */ -inline void Mesh::getBarycenter(UInt element, const ElementType & type, +inline void Mesh::getBarycenter(UInt element, const ElementType & type, Real * barycenter, GhostType ghost_type) const { AKANTU_DEBUG_IN(); - UInt * conn_val = getConnectivity(type,ghost_type).values; + UInt * conn_val = getConnectivity(type, ghost_type).values; UInt nb_nodes_per_element = getNbNodesPerElement(type); Real local_coord[spatial_dimension * nb_nodes_per_element]; UInt offset = element * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->values + conn_val[offset + n] * spatial_dimension, spatial_dimension*sizeof(Real)); } Math::barycenter(local_coord, nb_nodes_per_element, spatial_dimension, barycenter); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -inline const Vector & Mesh::getSurfaceId(const ElementType & type) const{ - AKANTU_DEBUG_IN(); +inline void Mesh::setSurfaceIDsFromIntData(std::string & data_name) { + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; - AKANTU_DEBUG_ASSERT(surface_id[type] != NULL, - "No element of kind : " << type << " in " << id); + const Mesh::ConnectivityTypeList & type_list = getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + if(Mesh::getSpatialDimension(*it) != spatial_dimension - 1) continue; - AKANTU_DEBUG_OUT(); - return *surface_id[type]; -} - -/* -------------------------------------------------------------------------- */ -inline void Mesh::setSurfaceIdsFromIntData(std::string & data_name) { - const Mesh::ConnectivityTypeList & type_list = getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension - 1) continue; + UIntDataMap & map = uint_data(*it, gt); + UIntDataMap::iterator it_data = map.find(data_name); + AKANTU_DEBUG_ASSERT(it_data != map.end(), + "No data named " << data_name + << " present in the mesh " << id + << " for the element type " << *it); + AKANTU_DEBUG_ASSERT(!surface_id.exists(*it, gt), + "Surface id for type (" << gt << ":" << *it + << ") already set to the vector " << surface_id(*it, gt)->getID()); - UIntDataMap::iterator it_data = uint_data[*it].find(data_name); - AKANTU_DEBUG_ASSERT(it_data != uint_data[*it].end(), - "No data named " << data_name - << " present in the mesh " << id - << " for the element type " << *it); - AKANTU_DEBUG_ASSERT(surface_id[*it] == NULL, - "Surface id for type " << *it - << " already set to the vector " << surface_id[*it]->getID()); - - surface_id[*it] = it_data->second; - } - - const Mesh::ConnectivityTypeList & ghost_type_list = getConnectivityTypeList(_ghost); - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension - 1) continue; - - UIntDataMap::iterator it_data = ghost_uint_data[*it].find(data_name); - AKANTU_DEBUG_ASSERT(it_data != ghost_uint_data[*it].end(), - "No data named " << data_name - << " present in the mesh " << id - << " for the element type " << *it); - AKANTU_DEBUG_ASSERT(ghost_surface_id[*it] == NULL, - "Surface id for type " << *it - << " already set to the vector " << ghost_surface_id[*it]->getID()); - - ghost_surface_id[*it] = it_data->second; + surface_id(*it, gt) = it_data->second; + } } } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbNodesPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt nb_nodes_per_element = 0; #define GET_NB_NODES_PER_ELEMENT(type) \ nb_nodes_per_element = ElementClass::getNbNodesPerElement() AKANTU_BOOST_ELEMENT_SWITCH(GET_NB_NODES_PER_ELEMENT); #undef GET_NB_NODES_PER_ELEMENT AKANTU_DEBUG_OUT(); return nb_nodes_per_element; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getP1ElementType(const ElementType & type) { AKANTU_DEBUG_IN(); ElementType element_p1 = _not_defined; #define GET_ELEMENT_P1(type) \ element_p1 = ElementClass::getP1ElementType() AKANTU_BOOST_ELEMENT_SWITCH(GET_ELEMENT_P1); #undef GET_NB_NODES_PER_ELEMENT_P1 AKANTU_DEBUG_OUT(); return element_p1; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getSpatialDimension(const ElementType & type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = 0; #define GET_SPATIAL_DIMENSION(type) \ spatial_dimension = ElementClass::getSpatialDimension() AKANTU_BOOST_ELEMENT_SWITCH(GET_SPATIAL_DIMENSION); #undef GET_SPATIAL_DIMENSION AKANTU_DEBUG_OUT(); return spatial_dimension; } /* -------------------------------------------------------------------------- */ inline ElementType Mesh::getFacetElementType(const ElementType & type) { AKANTU_DEBUG_IN(); ElementType surface_type = _not_defined; #define GET_FACET_TYPE(type) \ surface_type = ElementClass::getFacetElementType() AKANTU_BOOST_ELEMENT_SWITCH(GET_FACET_TYPE); #undef GET_FACET_TYPE AKANTU_DEBUG_OUT(); return surface_type; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbFacetsPerElement(const ElementType & type) { AKANTU_DEBUG_IN(); UInt n_facet = 0; #define GET_NB_FACET(type) \ n_facet = ElementClass::getNbFacetsPerElement() AKANTU_BOOST_ELEMENT_SWITCH(GET_NB_FACET); #undef GET_NB_FACET AKANTU_DEBUG_OUT(); return n_facet; } /* -------------------------------------------------------------------------- */ inline UInt ** Mesh::getFacetLocalConnectivity(const ElementType & type) { AKANTU_DEBUG_IN(); UInt ** facet_conn = NULL; #define GET_FACET_CON(type) \ facet_conn = ElementClass::getFacetLocalConnectivityPerElement() AKANTU_BOOST_ELEMENT_SWITCH(GET_FACET_CON); #undef GET_FACET_CON AKANTU_DEBUG_OUT(); return facet_conn; } /* -------------------------------------------------------------------------- */ inline void Mesh::extractNodalCoordinatesFromElement(Real * local_coord, UInt * connectivity, UInt n_nodes){ for (UInt n = 0; n < n_nodes; ++n) { memcpy(local_coord + n * spatial_dimension, nodes->values + connectivity[n] * spatial_dimension, spatial_dimension * sizeof(Real)); } } /* -------------------------------------------------------------------------- */ // inline void Mesh::extractNodalCoordinatesFromPBCElement(Real * local_coord, // UInt * connectivity, // UInt n_nodes){ - + // // get the min max of the element coordinates in all directions // Real min[3]; // Real max[3]; - + // for (UInt k = 0; k < spatial_dimension; k++) { // min[k] = std::numeric_limits::max(); // max[k] = std::numeric_limits::min(); // } - + // for (UInt nd = 0; nd < n_nodes; nd++) { // Real * coord = nodes->values + connectivity[nd] * spatial_dimension; // for (UInt k = 0; k < spatial_dimension; ++k) { // min[k] = std::min(min[k],coord[k]); // max[k] = std::max(max[k],coord[k]); // } // } // Real center[3]; // // compute the center of the element // for (UInt k = 0; k < spatial_dimension; ++k) { // center[k] = (max[k] + min[k])/2; // } // // reverse the coordinates that needs it // Real * lcoord = local_coord; // for (UInt n = 0; n < n_nodes; ++n) { // Real * coord = nodes->values + connectivity[n] * spatial_dimension; // for (UInt k = 0; k < spatial_dimension; ++k, ++coord,++lcoord) { // // if not at a border then copy normally the node // if (!pbc_directions[k] || fabs(xmax[k] - *coord) > Math::tolerance){ // *lcoord = *coord; // } // // else if distance from center is larger than global box size // // reverting is needed // else if (fabs(min[k] - *coord) > size[k]/2-Math::tolerance){ // *lcoord = *coord - size[k]; // } // else { // *lcoord = *coord; // } // } // } // } /* -------------------------------------------------------------------------- */ inline void Mesh::addConnecticityType(const ElementType & type){ getConnectivityPointer(type); } /* -------------------------------------------------------------------------- */ inline bool Mesh::isPureGhostNode(UInt n) const { return nodes_type ? (*nodes_type)(n) == -3 : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalOrMasterNode(UInt n) const { return nodes_type ? (*nodes_type)(n) == -2 || (*nodes_type)(n) == -1 : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isLocalNode(UInt n) const { return nodes_type ? (*nodes_type)(n) == -1 : true; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isMasterNode(UInt n) const { return nodes_type ? (*nodes_type)(n) == -2 : false; } /* -------------------------------------------------------------------------- */ inline bool Mesh::isSlaveNode(UInt n) const { return nodes_type ? (*nodes_type)(n) >= 0 : false; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNodeGlobalId(UInt local_id) const { return nodes_global_ids ? (*nodes_global_ids)(local_id) : local_id; } /* -------------------------------------------------------------------------- */ inline UInt Mesh::getNbGlobalNodes() const { return nodes_global_ids ? nb_global_nodes : nodes->getSize(); } /* -------------------------------------------------------------------------- */ inline Int Mesh::getNodeType(UInt local_id) const { return nodes_type ? (*nodes_type)(local_id) : -1; } + +/* -------------------------------------------------------------------------- */ +/* ByElementType */ /* -------------------------------------------------------------------------- */ -inline Mesh::UIntDataMap & Mesh::getUIntDataMap(const ElementType & el_type, - const GhostType & ghost_type){ - if (ghost_type == _not_ghost) - return uint_data[el_type]; - return ghost_uint_data[el_type]; -}; /* -------------------------------------------------------------------------- */ -inline const Vector & Mesh::getConnectivity(const ElementType & el_type, - const GhostType & ghost_type) const{ - if (ghost_type == _not_ghost) - return *connectivities[el_type]; +template +inline std::string ByElementType::printType(const ElementType & type, + const GhostType & ghost_type) { + std::stringstream sstr; sstr << "(" << ghost_type << ":" << type << ")"; + return sstr.str(); +} + +/* -------------------------------------------------------------------------- */ +template +inline bool ByElementType::exists(ElementType type, GhostType ghost_type) const { + return this->getData(ghost_type).find(type) != this->getData(ghost_type).end(); +} + +/* -------------------------------------------------------------------------- */ +template +inline const Stored & ByElementType::operator()(const ElementType & type, + const GhostType & ghost_type) const { + typename ByElementType::DataMap::const_iterator it = + this->getData(ghost_type).find(type); + + AKANTU_DEBUG_ASSERT(it != this->getData(ghost_type).end(), + "No element of type " + << ByElementType::printType(type, ghost_type) + << " in this ByElementType<" + << debug::demangle(typeid(Stored).name()) << "> class"); + return it->second; +} + +/* -------------------------------------------------------------------------- */ +template +inline Stored & ByElementType::operator()(const ElementType & type, + const GhostType & ghost_type) { + typename ByElementType::DataMap::iterator it = + this->getData(ghost_type).find(type); + + if(it == this->getData(ghost_type).end()) { + ByElementType::DataMap & data = this->getData(ghost_type); + const std::pair & res = + data.insert(std::pair(type, Stored())); + it = res.first; + } + + return it->second; +} + +/* -------------------------------------------------------------------------- */ +template +inline typename ByElementType::DataMap & ByElementType::getData(GhostType ghost_type) { + if(ghost_type == _not_ghost) return data; + else if (ghost_type == _ghost) return ghost_data; +} + +/* -------------------------------------------------------------------------- */ +template +inline const typename ByElementType::DataMap & ByElementType::getData(GhostType ghost_type) const { + if(ghost_type == _not_ghost) return data; + else if (ghost_type == _ghost) return ghost_data; +} + +/* -------------------------------------------------------------------------- */ +/// Works only if stored is a pointer to a class with a printself method +template +void ByElementType::printself(std::ostream & stream, int indent) const { + std::string space; + for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); + + stream << "ByElementType<" << debug::demangle(typeid(Stored).name()) << "> [" << std::endl; + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + + const ByElementType::DataMap & data = getData(gt); + typename ByElementType::DataMap::const_iterator it; + for(it = data.begin(); it != data.end(); ++it) { + stream << space << debug::demangle(typeid(Stored).name()) + << ByElementType::printType(it->first, gt) << " [" << std::endl; + it->second->printself(stream, indent + 2); + } + } +} - return *ghost_connectivities[el_type]; -}; /* -------------------------------------------------------------------------- */ +template +ByElementType::ByElementType() { + AKANTU_DEBUG_IN(); + AKANTU_DEBUG_OUT(); +} +/* -------------------------------------------------------------------------- */ +template +ByElementType::~ByElementType() { + +} diff --git a/fem/shape_lagrange.cc b/fem/shape_lagrange.cc index dbbf49ee0..449adcae5 100644 --- a/fem/shape_lagrange.cc +++ b/fem/shape_lagrange.cc @@ -1,403 +1,372 @@ /** * @file shape_lagrange.cc * @author Guillaume Anciaux * @author Nicolas Richart * @date Thu Feb 10 11:45:51 2011 * * @brief lagrangian shape functions class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" #include "shape_lagrange.hh" #include "element_class.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ShapeLagrange::ShapeLagrange(Mesh & mesh,ShapeID id):ShapeFunctions(mesh,id){ - for(UInt t = _not_defined; t < _max_element_type; ++t) { - this->shapes [t] = NULL; - this->ghost_shapes [t] = NULL; - this->shapes_derivatives[t] = NULL; - this->ghost_shapes_derivatives[t] = NULL; - } + AKANTU_DEBUG_IN(); + + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void ShapeLagrange::precomputeShapesOnControlPoints(GhostType ghost_type) { AKANTU_DEBUG_IN(); - Real * natural_coords = control_points[type]->values; - UInt nb_points = control_points[type]->getSize(); + Real * natural_coords = control_points(type, ghost_type)->values; + UInt nb_points = control_points(type, ghost_type)->getSize(); UInt size_of_shapes = ElementClass::getShapeSize(); - UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize();; + UInt nb_element = mesh->getConnectivity(type, ghost_type).getSize();; std::string ghost = ""; if(ghost_type == _ghost) { ghost = "ghost_"; } std::stringstream sstr_shapes; sstr_shapes << id << ":" << ghost << "shapes:" << type; Vector * shapes_tmp = &(alloc(sstr_shapes.str(), nb_element*nb_points, size_of_shapes)); Real * shapes_val = shapes_tmp->values; for (UInt elem = 0; elem < nb_element; ++elem) { ElementClass::computeShapes(natural_coords, nb_points,shapes_val); shapes_val += size_of_shapes*nb_points; } - if(ghost_type == _not_ghost) { - shapes[type] = shapes_tmp; - } else { - ghost_shapes[type] = shapes_tmp; - } + shapes(type, ghost_type) = shapes_tmp; + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void ShapeLagrange::precomputeShapeDerivativesOnControlPoints(GhostType ghost_type) { AKANTU_DEBUG_IN(); // Real * coord = mesh->getNodes().values; UInt spatial_dimension = mesh->getSpatialDimension(); - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt size_of_shapesd = ElementClass::getShapeDerivativesSize(); - Real * natural_coords = control_points[type]->values; - UInt nb_points = control_points[type]->getSize(); + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); + UInt size_of_shapesd = ElementClass::getShapeDerivativesSize(); + UInt nb_points = control_points(type, ghost_type)->getSize(); + Real * natural_coords = control_points(type, ghost_type)->values; + - UInt * elem_val = mesh->getConnectivity(type,ghost_type).values;; - UInt nb_element = mesh->getConnectivity(type,ghost_type).getSize(); + UInt * elem_val = mesh->getConnectivity(type, ghost_type).values;; + UInt nb_element = mesh->getConnectivity(type, ghost_type).getSize(); std::string ghost = ""; if(ghost_type == _ghost) { ghost = "ghost_"; } std::stringstream sstr_shapesd; sstr_shapesd << id << ":" << ghost << "shapes_derivatives:" << type; Vector * shapes_derivatives_tmp = &(alloc(sstr_shapesd.str(), nb_element*nb_points, size_of_shapesd)); Real * shapesd_val = shapes_derivatives_tmp->values; Real local_coord[spatial_dimension * nb_nodes_per_element]; for (UInt elem = 0; elem < nb_element; ++elem) { mesh->extractNodalCoordinatesFromElement(local_coord, elem_val+elem*nb_nodes_per_element, nb_nodes_per_element); - + computeShapeDerivativesOnCPointsByElement(spatial_dimension, local_coord,nb_nodes_per_element, natural_coords,nb_points, shapesd_val); shapesd_val += size_of_shapesd*nb_points; } - if(ghost_type == _not_ghost) { - shapes_derivatives[type] = shapes_derivatives_tmp; - } else { - ghost_shapes_derivatives[type] = shapes_derivatives_tmp; - } + + shapes_derivatives(type, ghost_type) = shapes_derivatives_tmp; + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void ShapeLagrange::interpolateOnControlPoints(const Vector &in_u, Vector &out_uq, UInt nb_degre_of_freedom, GhostType ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); - Vector * shapes_loc; - UInt nb_element = mesh->getNbElement(type,ghost_type); - UInt * conn_val = mesh->getConnectivity(type,ghost_type).values; - if(ghost_type == _not_ghost) { - shapes_loc = shapes[type]; - } else { - shapes_loc = ghost_shapes[type]; - } + UInt nb_element = mesh->getNbElement(type, ghost_type); + UInt * conn_val = mesh->getConnectivity(type, ghost_type).values; + + AKANTU_DEBUG_ASSERT(shapes.exists(type, ghost_type), + "No shapes for the type " + << shapes.printType(type, ghost_type)); - AKANTU_DEBUG_ASSERT(shapes_loc != NULL, - "No shapes for the type " << type); + Vector * shapes_loc = shapes(type, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_points = control_points[type]->getSize(); + UInt nb_points = control_points(type, ghost_type)->getSize(); UInt size_of_shapes = ElementClass::getShapeSize(); AKANTU_DEBUG_ASSERT(in_u.getSize() == mesh->getNbNodes(), "The vector in_u(" << in_u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_u.getNbComponent() == nb_degre_of_freedom, "The vector in_u(" << in_u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(out_uq.getNbComponent() == nb_degre_of_freedom , "The vector out_uq(" << out_uq.getID() << ") has not the good number of component."); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } out_uq.resize(nb_element * nb_points); Real * shape_val = shapes_loc->values; Real * u_val = in_u.values; Real * uq_val = out_uq.values; - UInt offset_uq = out_uq.getNbComponent()*nb_points; + UInt offset_uq = out_uq.getNbComponent() * nb_points; Real * shape = shape_val; - Real * u = static_cast(calloc(nb_nodes_per_element * nb_degre_of_freedom, - sizeof(Real))); + Real * u = new Real[nb_nodes_per_element * nb_degre_of_freedom]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { - shape = shape_val + filter_elem_val[el] * size_of_shapes*nb_points; + shape = shape_val + filter_elem_val[el] * size_of_shapes * nb_points; el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(u + n * nb_degre_of_freedom, u_val + conn_val[el_offset + n] * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Real)); } - /// Uq = Shape * U : matrix product + /// @f$ u_q = \textbf{N} * u @f$ Math::matrix_matrix(nb_points, nb_degre_of_freedom, nb_nodes_per_element, shape, u, uq_val); uq_val += offset_uq; if(filter_elements == NULL) { shape += size_of_shapes*nb_points; } } - free(u); + delete [] u; #undef INIT_VARIABLES AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void ShapeLagrange::gradientOnControlPoints(const Vector &in_u, Vector &out_nablauq, UInt nb_degre_of_freedom, GhostType ghost_type, const Vector * filter_elements) const { AKANTU_DEBUG_IN(); - Vector * shapesd_loc; - UInt nb_element = mesh->getNbElement(type,ghost_type); - UInt * conn_val = mesh->getConnectivity(type,ghost_type).values;; - if(ghost_type == _not_ghost) { - shapesd_loc = shapes_derivatives[type]; - } else { - shapesd_loc = ghost_shapes_derivatives[type]; - } + UInt nb_element = mesh->getNbElement(type, ghost_type); + UInt * conn_val = mesh->getConnectivity(type, ghost_type).values;; + + Vector * shapesd_loc = shapes_derivatives(type, ghost_type); - AKANTU_DEBUG_ASSERT(shapesd_loc != NULL, - "No shapes for the type " << type); + AKANTU_DEBUG_ASSERT(shapes_derivatives.exists(type, ghost_type), + "No shapes derivatives for the type " + << shapes_derivatives.printType(type, ghost_type)); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt size_of_shapes_derivatives = ElementClass::getShapeDerivativesSize(); - UInt nb_points = control_points[type]->getSize(); + UInt nb_points = control_points(type, ghost_type)->getSize(); UInt element_dimension = ElementClass::getSpatialDimension(); UInt * filter_elem_val = NULL; if(filter_elements != NULL) { nb_element = filter_elements->getSize(); filter_elem_val = filter_elements->values; } AKANTU_DEBUG_ASSERT(in_u.getSize() == mesh->getNbNodes(), "The vector in_u(" << in_u.getID() << ") has not the good size."); AKANTU_DEBUG_ASSERT(in_u.getNbComponent() == nb_degre_of_freedom , "The vector in_u(" << in_u.getID() << ") has not the good number of component."); AKANTU_DEBUG_ASSERT(out_nablauq.getNbComponent() == nb_degre_of_freedom * element_dimension, "The vector out_nablauq(" << out_nablauq.getID() << ") has not the good number of component."); out_nablauq.resize(nb_element * nb_points); Real * shaped_val = shapesd_loc->values; Real * u_val = in_u.values; Real * nablauq_val = out_nablauq.values; UInt offset_nablauq = nb_degre_of_freedom * element_dimension; UInt offset_shaped = nb_nodes_per_element * element_dimension; Real * shaped = shaped_val; - Real * u = static_cast(calloc(nb_nodes_per_element * nb_degre_of_freedom, - sizeof(Real))); + Real * u = new Real[nb_nodes_per_element * nb_degre_of_freedom]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; if(filter_elements != NULL) { shaped = shaped_val + filter_elem_val[el] * size_of_shapes_derivatives*nb_points; el_offset = filter_elem_val[el] * nb_nodes_per_element; } for (UInt n = 0; n < nb_nodes_per_element; ++n) { memcpy(u + n * nb_degre_of_freedom, u_val + conn_val[el_offset + n] * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Real)); } for (UInt q = 0; q < nb_points; ++q) { - /// \nabla(U) = U^t * dphi/dx + /// @f$\nabla u^t = u^t * B^t@f$ Math::matrixt_matrix(nb_degre_of_freedom, element_dimension, nb_nodes_per_element, u, shaped, nablauq_val); nablauq_val += offset_nablauq; shaped += offset_shaped; } } - free(u); + delete [] u; #undef INIT_VARIABLES AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template -void ShapeLagrange::setControlPointsByType(Vector & points){ - control_points[type] = &points; +void ShapeLagrange::setControlPointsByType(Vector & points, GhostType ghost_type){ + control_points(type, ghost_type) = &points; } /* -------------------------------------------------------------------------- */ template void ShapeLagrange::fieldTimesShapes(const Vector & field, Vector & field_times_shapes, GhostType ghost_type) { field_times_shapes.copy(field); field_times_shapes.extendComponentsInterlaced(ElementClass::getShapeSize(), 1); UInt nb_element = field_times_shapes.getSize() * ElementClass::getShapeSize(); Real * field_times_shapes_val = field_times_shapes.values; - Real * shapes_val; - if(ghost_type == _not_ghost) { - shapes_val = shapes[type]->values; - } else { - shapes_val = ghost_shapes[type]->values; - } + Real * shapes_val = shapes(type, ghost_type)->values; + /// compute @f$ rho * \varphi_i @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { *field_times_shapes_val++ *= *shapes_val++; } } /* -------------------------------------------------------------------------- */ void ShapeLagrange::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Shapes Lagrange [" << std::endl; - for(UInt type = _not_defined; type < _max_element_type; ++type) { - if(shapes[type]) - shapes[type]->printself(stream, indent + 1); - - if(ghost_shapes[type]) - ghost_shapes[type]->printself(stream, indent + 1); - - if(shapes_derivatives[type]) - shapes_derivatives[type]->printself(stream, indent + 1); - - if(ghost_shapes_derivatives[type]) - ghost_shapes_derivatives[type]->printself(stream, indent + 1); - - if(control_points[type]) - control_points[type]->printself(stream, indent + 1); + for(UInt t = _not_defined; t < _max_element_type; ++t) { + ElementType type = (ElementType) t; + shapes.printself(stream, indent + 1); + shapes_derivatives.printself(stream, indent + 1); + control_points.printself(stream, indent + 1); } stream << space << "]" << std::endl; - - } /* -------------------------------------------------------------------------- */ /* template instanciation */ /* -------------------------------------------------------------------------- */ #define INSTANCIATE_TEMPLATE_CLASS(type) \ template \ void ShapeLagrange::precomputeShapesOnControlPoints(GhostType ghost_type); \ template \ void ShapeLagrange::precomputeShapeDerivativesOnControlPoints(GhostType ghost_type); \ template \ - void ShapeLagrange::setControlPointsByType(Vector & control_points); \ + void ShapeLagrange::setControlPointsByType(Vector & control_points, GhostType ghost_type); \ template \ void ShapeLagrange::gradientOnControlPoints(const Vector &in_u, \ Vector &out_nablauq, \ UInt nb_degre_of_freedom, \ GhostType ghost_type, \ const Vector * filter_elements) const; \ template \ void ShapeLagrange::interpolateOnControlPoints(const Vector &in_u, \ Vector &out_uq, \ UInt nb_degre_of_freedom, \ GhostType ghost_type, \ const Vector * filter_elements) const; \ template \ void ShapeLagrange::fieldTimesShapes(const Vector & field, \ Vector & field_times_shapes, \ GhostType ghost_type); AKANTU_BOOST_ELEMENT_LIST(INSTANCIATE_TEMPLATE_CLASS) #undef INSTANCIATE_TEMPLATE_CLASS __END_AKANTU__ diff --git a/fem/shape_lagrange.hh b/fem/shape_lagrange.hh index 990813a7d..e34d20670 100644 --- a/fem/shape_lagrange.hh +++ b/fem/shape_lagrange.hh @@ -1,166 +1,150 @@ /** * @file shape_lagrange.hh * @author Guillaume Anciaux * @date Thu Feb 10 11:44:29 2011 * * @brief lagrangian shape functions class * * @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 . * */ #ifndef __AKANTU_SHAPE_LAGRANGE_HH__ #define __AKANTU_SHAPE_LAGRANGE_HH__ #include "shape_functions.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ class ShapeLagrange : public ShapeFunctions{ /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: ShapeLagrange(Mesh & mesh,ShapeID id="shapeLagrange"); virtual ~ShapeLagrange(){}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// pre compute all shapes on the element control points from natural coordinates template void precomputeShapesOnControlPoints(GhostType ghost_type); /// pre compute all shapes on the element control points from natural coordinates template void precomputeShapeDerivativesOnControlPoints(GhostType ghost_type); /// interpolate nodal values on the control points template void interpolateOnControlPoints(const Vector &u, Vector &uq, UInt nb_degre_of_freedom, GhostType ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// compute the gradient of u on the control points template void gradientOnControlPoints(const Vector &u, Vector &nablauq, UInt nb_degre_of_freedom, GhostType ghost_type = _not_ghost, const Vector * filter_elements = NULL) const; /// set the control points for a given element template - void setControlPointsByType(Vector & control_points); + void setControlPointsByType(Vector & control_points, GhostType ghost_type); /// multiply a field by shape functions template void fieldTimesShapes(const Vector & field, Vector & fiedl_times_shapes, GhostType ghost_type); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// compute the shape derivatives on control points for a given element template inline void computeShapeDerivativesOnCPointsByElement(UInt spatial_dimension, Real * node_coords, UInt nb_nodes_per_element, Real * natural_coords, UInt nb_points, Real * shapesd); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get a the shapes vector - const Vector & getShapes(const ElementType & type, const GhostType & ghost_type); - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Shapes, shapes, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Shapes, shapes, Real); /// get a the shapes derivatives vector - const Vector & getShapesDerivatives(const ElementType & type, const GhostType & ghost_type); - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ShapesDerivatives, shapes_derivatives, const Vector &); - - // /// get a the ghost shapes vector - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostShapes, ghost_shapes, - // const Vector &); - - /// get a the ghost shapes derivatives vector - // AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostShapesDerivatives, ghost_shapes_derivatives, - // const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ShapesDerivatives, shapes_derivatives, Real); /// get the size of the shapes returned by the element class static inline UInt getShapeSize(const ElementType & type); /// get the size of the shapes derivatives returned by the element class static inline UInt getShapeDerivativesSize(const ElementType & type); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// shape functions for all elements ByElementTypeReal shapes; - /// shape functions for all elements - ByElementTypeReal ghost_shapes; - /// shape derivatives for all elements ByElementTypeReal shapes_derivatives; - /// shape derivatives for all elements - ByElementTypeReal ghost_shapes_derivatives; - /// shape functions for all elements ByElementTypeReal control_points; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "shape_lagrange_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const ShapeLagrange & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_SHAPE_LAGRANGE_HH__ */ diff --git a/fem/shape_lagrange_inline_impl.cc b/fem/shape_lagrange_inline_impl.cc index 7ed6a7e75..dc5f16af2 100644 --- a/fem/shape_lagrange_inline_impl.cc +++ b/fem/shape_lagrange_inline_impl.cc @@ -1,93 +1,77 @@ /** * @file shape_lagrange_inline_impl.cc * @author Guillaume Anciaux * @date Thu Feb 10 21:12:54 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 . * */ /* -------------------------------------------------------------------------- */ inline UInt ShapeLagrange::getShapeSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_size = 0; #define GET_SHAPE_SIZE(type) \ shape_size = ElementClass::getShapeSize() AKANTU_BOOST_ELEMENT_SWITCH(GET_SHAPE_SIZE); #undef GET_SHAPE_SIZE AKANTU_DEBUG_OUT(); return shape_size; } /* -------------------------------------------------------------------------- */ inline UInt ShapeLagrange::getShapeDerivativesSize(const ElementType & type) { AKANTU_DEBUG_IN(); UInt shape_derivatives_size = 0; #define GET_SHAPE_DERIVATIVES_SIZE(type) \ shape_derivatives_size = ElementClass::getShapeDerivativesSize() AKANTU_BOOST_ELEMENT_SWITCH(GET_SHAPE_DERIVATIVES_SIZE); #undef GET_SHAPE_DERIVATIVES_SIZE AKANTU_DEBUG_OUT(); return shape_derivatives_size; } /* -------------------------------------------------------------------------- */ template inline void ShapeLagrange:: computeShapeDerivativesOnCPointsByElement(UInt spatial_dimension, Real * node_coords, UInt nb_nodes_per_element, Real * natural_coords, UInt nb_points, Real * shapesd) { // compute dnds Real dnds[nb_nodes_per_element * spatial_dimension * nb_points]; ElementClass::computeDNDS(natural_coords, nb_points, dnds); // compute dxds Real dxds[spatial_dimension * spatial_dimension * nb_points]; ElementClass::computeDXDS(dnds, nb_points, node_coords, spatial_dimension, dxds); // compute shape derivatives ElementClass::computeShapeDerivatives(dxds, dnds, nb_points, spatial_dimension, shapesd); } -/* -------------------------------------------------------------------------- */ -inline const Vector & ShapeLagrange::getShapes(const ElementType & type, - const GhostType & ghost_type){ - if (ghost_type == _not_ghost) - return *shapes[type]; - - return *ghost_shapes[type]; -} -/* -------------------------------------------------------------------------- */ -inline const Vector & ShapeLagrange::getShapesDerivatives(const ElementType & type, - const GhostType & ghost_type){ - if (ghost_type == _not_ghost) - return *shapes_derivatives[type]; - return *ghost_shapes_derivatives[type]; -} - diff --git a/mesh_utils/mesh_io/mesh_io_diana.cc b/mesh_utils/mesh_io/mesh_io_diana.cc index c1b5a2fa0..24407b4e6 100644 --- a/mesh_utils/mesh_io/mesh_io_diana.cc +++ b/mesh_utils/mesh_io/mesh_io_diana.cc @@ -1,501 +1,501 @@ /** * @file mesh_io_diana.cc * @author Alodie Schneuwly * @author David Kammer * @date Thu Mar 10 15:42:24 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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "mesh_io_diana.hh" /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIODiana::MeshIODiana() { canReadSurface = true; canReadExtendedData = true; _diana_to_akantu_element_types["TE12L"] = _tetrahedron_4; _diana_to_akantu_element_types["HX24L"] = _hexahedron_8; _diana_to_akantu_mat_prop["YOUNG"] = "E"; _diana_to_akantu_mat_prop["DENSIT"] = "rho"; _diana_to_akantu_mat_prop["POISON"] = "nu"; } /* -------------------------------------------------------------------------- */ MeshIODiana::~MeshIODiana() { std::map *>::iterator ng_it; std::map *>::iterator eg_it; for (ng_it = node_groups.begin(); ng_it != node_groups.end(); ++ng_it) { delete ng_it->second; } for (eg_it = element_groups.begin(); eg_it != element_groups.end(); ++eg_it) { delete eg_it->second; } } /* -------------------------------------------------------------------------- */ inline void my_getline(std::ifstream & infile, std::string & line) { std::getline(infile, line); //read the line size_t pos = line.find("\r"); /// remove the extra \r if needed line = line.substr(0, pos); } /* -------------------------------------------------------------------------- */ void MeshIODiana::read(const std::string & filename, Mesh & mesh) { AKANTU_DEBUG_IN(); std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits::max(); std::vector global_to_local_index; if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while(infile.good()) { my_getline(infile, line); /// read all nodes if(line == "'COORDINATES'") { line = readCoordinates(infile, mesh, first_node_number); } /// read all elements if (line == "'ELEMENTS'") { line = readElements(infile, mesh, global_to_local_index, first_node_number); } /// read the material properties and write a .dat file if (line == "'MATERIALS'") { line = readMaterial(infile, mesh, filename); } /// read the material properties and write a .dat file if (line == "'GROUPS'") { line = readGroups(infile, mesh, global_to_local_index, first_node_number); } } infile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshIODiana::write(const std::string & filename, const Mesh & mesh) { } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readCoordinates(std::ifstream & infile, Mesh & mesh, UInt & first_node_number) { AKANTU_DEBUG_IN(); Vector & nodes = const_cast &>(mesh.getNodes()); std::string line; UInt index; Real coord[3]; do { my_getline(infile, line); if("'ELEMENTS'" == line) break; //end = true; //else { /// for each node, read the coordinates std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; //if (!sstr_node.fail()) //break; first_node_number = first_node_number < index ? first_node_number : index; nodes.push_back(coord); // } } while(true);//!end); AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ UInt MeshIODiana::readInterval(std::stringstream & line, std::set & interval) { UInt first; line >> first; if(line.fail()) { return 0; } interval.insert(first); UInt second; char dash; dash = line.get(); if(dash == '-') { line >> second; interval.insert(second); return 2; } if(line.fail()) line.clear(std::ios::eofbit); // in case of get at end of the line else line.unget(); return 1; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readGroups(std::ifstream & infile, Mesh & mesh, std::vector & global_to_local_index, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); bool reading_nodes_group = false; while(line != "'SUPPORTS'") { if(line == "NODES") { reading_nodes_group = true; // std::cout << line << std::endl; my_getline(infile, line); } if(line == "ELEMEN") { reading_nodes_group = false; // std::cout << line << std::endl; my_getline(infile, line); } std::stringstream *str = new std::stringstream(line); UInt id; std::string name; char c; *str >> id >> name >> c; // std::cout << id << " " << name << " " << c << std::endl; Vector * list_ids = new Vector(0,1); UInt s = 1; bool end = false; while(!end) { while(!str->eof() && s != 0) { std::set interval; s = readInterval(*str, interval); std::set::iterator it = interval.begin(); if(s == 1) list_ids->push_back(*it); if(s == 2) { UInt first = *it; ++it; UInt second = *it; for(UInt i = first; i <= second; ++i) { list_ids->push_back(i); } } } if(str->fail()) end = true; else { my_getline(infile, line); delete str; str = new std::stringstream(line); } } delete str; if(reading_nodes_group) { for (UInt i = 0; i < list_ids->getSize(); ++i) { (*list_ids)(i) -= first_node_number; } node_groups[name] = list_ids; } else { std::vector * elem = new std::vector; elem->reserve(list_ids->getSize()); for (UInt i = 0; i < list_ids->getSize(); ++i) { elem->push_back(global_to_local_index[(*list_ids)(i)-1]); } element_groups[name] = elem; delete list_ids; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readElements(std::ifstream & infile, Mesh & mesh, std::vector & global_to_local_index, UInt first_node_number) { AKANTU_DEBUG_IN(); std::string line; my_getline(infile, line); if("CONNECTIVITY" == line) { line = readConnectivity(infile, mesh, global_to_local_index, first_node_number); } /// read the line corresponding to the materials if ("MATERIALS" == line) { line = readMaterialElement(infile, mesh, global_to_local_index); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readConnectivity(std::ifstream & infile, Mesh & mesh, std::vector & global_to_local_index, UInt first_node_number) { AKANTU_DEBUG_IN(); Int index; std::string lline; std::string diana_type; ElementType akantu_type, akantu_type_old = _not_defined; Vector *connectivity = NULL; UInt node_per_element = 0; Element elem; UInt nb_elements_type = 0; bool end = false; do { my_getline(infile, lline); std::stringstream sstr_elem(lline); if(lline == "MATERIALS") end = true; else { /// traiter les coordonnees sstr_elem >> index; sstr_elem >> diana_type; akantu_type = _diana_to_akantu_element_types[diana_type]; if(akantu_type != akantu_type_old) { connectivity = mesh.getConnectivityPointer(akantu_type); connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; nb_elements_type = 0; } UInt local_connect[node_per_element]; for(UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; node_index -= first_node_number; local_connect[j] = node_index; } connectivity->push_back(local_connect); elem.type = akantu_type; elem.element = nb_elements_type; global_to_local_index.push_back(elem); nb_elements_type++; } } while(!end); AKANTU_DEBUG_OUT(); return lline; } /* -------------------------------------------------------------------------- */ UInt readInterval(std::stringstream & line, std::set & interval) { UInt first; line >> first; if(line.fail()) { return 0; } interval.insert(first); UInt second; char ignored; line >> ignored >> second; if(line.fail()) { line.clear(); return 1; } interval.insert(second); return 2; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterialElement(std::ifstream & infile, Mesh & mesh, std::vector & global_to_local_index) { AKANTU_DEBUG_IN(); // Vector vector_elements(nb_elements,1); // ElementType akantu_type; std::string line; // bool end = false; // bool end_range = false; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << 0; //Vector * data = mesh.getUIntDataPointer(akantu_type, sstr_tag_name.str()); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { UInt nb_element = mesh.getNbElement(*it); - mesh.getUIntDataPointer(*it, "material")->resize(nb_element); + mesh.getUIntDataPointer(*it, "material", _not_ghost)->resize(nb_element); } my_getline(infile, line); while(line != "'MATERIALS'") { line = line.substr(line.find('/') + 1, std::string::npos); // erase the first slash / of the line char tutu[250]; strcpy(tutu, line.c_str()); Vector temp_id(0, 2); UInt mat; while(true){ std::stringstream sstr_intervals_elements(line); UInt id[2]; char temp; while(sstr_intervals_elements.good()) { sstr_intervals_elements >> id[0] >> temp >> id[1]; // >> "/" >> mat; if(!sstr_intervals_elements.fail()) temp_id.push_back(id); } if (sstr_intervals_elements.fail()) { sstr_intervals_elements.clear(); sstr_intervals_elements.ignore(); sstr_intervals_elements >> mat; break; } my_getline(infile, line); } // loop over elements // UInt * temp_id_val = temp_id.values; for (UInt i = 0; i < temp_id.getSize(); ++i) for (UInt j=temp_id(i,0); j<=temp_id(i,1); ++j) { Element & element = global_to_local_index[j - 1]; UInt elem = element.element; ElementType type = element.type; - Vector & data = *(mesh.getUIntDataPointer(type, "material")); + Vector & data = *(mesh.getUIntDataPointer(type, "material", _not_ghost)); data(elem) = mat; } my_getline(infile, line); } AKANTU_DEBUG_OUT(); return line; } /* -------------------------------------------------------------------------- */ std::string MeshIODiana::readMaterial(std::ifstream & infile, Mesh & mesh, const std::string & filename) { AKANTU_DEBUG_IN(); std::stringstream mat_file_name; mat_file_name << "material_" << filename; std::ofstream material_file; material_file.open(mat_file_name.str().c_str());//mat_file_name.str()); UInt mat_index; std::string line; bool first_mat = true; bool end = false; do{ my_getline(infile, line); std::stringstream sstr_material(line); if("'GROUPS'" == line) { material_file << "]" << std::endl; end = true; } else { /// traiter les caractéristiques des matériaux sstr_material >> mat_index; if(!sstr_material.fail()) { if(!first_mat) { material_file << "]" << std::endl; } material_file << "material elastic [" << std::endl; first_mat = false; } else { sstr_material.clear(); } std::string prop_name; sstr_material >> prop_name; std::map::iterator it; it = _diana_to_akantu_mat_prop.find(prop_name); if(it != _diana_to_akantu_mat_prop.end()) { Real value; sstr_material >> value; material_file << "\t" << it->second << " = " << value << std::endl; } else { //AKANTU_DEBUG_WARNING("In material reader, property " << it->first << "not recognized"); } } } while (!end); AKANTU_DEBUG_OUT(); return line; } __END_AKANTU__ diff --git a/mesh_utils/mesh_io/mesh_io_msh.cc b/mesh_utils/mesh_io/mesh_io_msh.cc index b1fd35723..72e7f4070 100644 --- a/mesh_utils/mesh_io/mesh_io_msh.cc +++ b/mesh_utils/mesh_io/mesh_io_msh.cc @@ -1,435 +1,435 @@ /** * @file mesh_io_msh.cc * @author Nicolas Richart * @date Fri Jun 18 11:36:35 2010 * * @brief Read/Write for MSH files generated by gmsh * * @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 . * */ /* ----------------------------------------------------------------------------- Version (Legacy) 1.0 $NOD number-of-nodes node-number x-coord y-coord z-coord ... $ENDNOD $ELM number-of-elements elm-number elm-type reg-phys reg-elem number-of-nodes node-number-list ... $ENDELM ----------------------------------------------------------------------------- Version 2.1 $MeshFormat version-number file-type data-size $EndMeshFormat $Nodes number-of-nodes node-number x-coord y-coord z-coord ... $EndNodes $Elements number-of-elements elm-number elm-type number-of-tags < tag > ... node-number-list ... $EndElements $PhysicalNames number-of-names physical-dimension physical-number "physical-name" ... $EndPhysicalNames $NodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... node-number value ... ... $EndNodeData $ElementData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number value ... ... $EndElementData $ElementNodeData number-of-string-tags < "string-tag" > ... number-of-real-tags < real-tag > ... number-of-integer-tags < integer-tag > ... elm-number number-of-nodes-per-element value ... ... $ElementEndNodeData ----------------------------------------------------------------------------- elem-type 1: 2-node line. 2: 3-node triangle. 3: 4-node quadrangle. 4: 4-node tetrahedron. 5: 8-node hexahedron. 6: 6-node prism. 7: 5-node pyramid. 8: 3-node second order line 9: 6-node second order triangle 10: 9-node second order quadrangle 11: 10-node second order tetrahedron 12: 27-node second order hexahedron 13: 18-node second order prism 14: 14-node second order pyramid 15: 1-node point. 16: 8-node second order quadrangle 17: 20-node second order hexahedron 18: 15-node second order prism 19: 13-node second order pyramid 20: 9-node third order incomplete triangle 21: 10-node third order triangle 22: 12-node fourth order incomplete triangle 23: 15-node fourth order triangle 24: 15-node fifth order incomplete triangle 25: 21-node fifth order complete triangle 26: 4-node third order edge 27: 5-node fourth order edge 28: 6-node fifth order edge 29: 20-node third order tetrahedron 30: 35-node fourth order tetrahedron 31: 56-node fifth order tetrahedron -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "mesh_io_msh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /* Constant arrays initialisation */ /* -------------------------------------------------------------------------- */ UInt MeshIOMSH::_read_order[_max_element_type][MAX_NUMBER_OF_NODE_PER_ELEMENT] = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // _not_defined { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, // _line1 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // _line2 { 0, 1, 2, 0, 0, 0, 0, 0, 0, 0 }, // _triangle_3 { 0, 1, 2, 3, 4, 5, 6, 0, 0, 0 }, // _triangle_6 { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 }, // _tetrahedron_4 { 0, 1, 2, 3, 4, 5, 6, 7, 9, 8 }, // _tetrahedron_10 { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0 }, // _quadrangle_4 { 0, 1, 2, 3, 4, 5, 6, 7, 0, 0 }, // _quadrangle_8 { 0, 1, 2, 3, 4, 5, 6, 7, 0, 0 } // _hexahedron_8 }; UInt MeshIOMSH::_msh_nodes_per_elem[17] = { 0, // element types began at 1 2, 3, 4, 4, 8, 6, 5, // 1st order 3, 6, 9, 10, 27, 18, 14, // 2st order 1, 8 }; ElementType MeshIOMSH::_msh_to_akantu_element_types[17] = { _not_defined, // element types began at 1 _segment_2, _triangle_3, _quadrangle_4, _tetrahedron_4, // 1st order _hexahedron_8, _not_defined, _not_defined, _segment_3, _triangle_6, _not_defined, _tetrahedron_10, // 2nd order _not_defined, _not_defined, _not_defined, _not_defined, _quadrangle_8 }; MeshIOMSH::MSHElementType MeshIOMSH::_akantu_to_msh_element_types[_max_element_type] = { _msh_not_defined, // _not_defined _msh_segment_2, // _segment_2 _msh_segment_3, // _segment_3 _msh_triangle_3, // _triangle_3 _msh_triangle_6, // _triangle_6 _msh_tetrahedron_4, // _tetrahedron_4 _msh_tetrahedron_10,// _tetrahedron_10 _msh_quadrangle_4, // _quadrangle_4 _msh_quadrangle_8, // _quadrangle_4 _msh_hexahedron_8 // _hexahedron_8 }; /* -------------------------------------------------------------------------- */ /* Methods Implentations */ /* -------------------------------------------------------------------------- */ MeshIOMSH::MeshIOMSH() { canReadSurface = false; canReadExtendedData = false; } /* -------------------------------------------------------------------------- */ MeshIOMSH::~MeshIOMSH() { } /* -------------------------------------------------------------------------- */ void MeshIOMSH::read(const std::string & filename, Mesh & mesh) { std::ifstream infile; infile.open(filename.c_str()); std::string line; UInt first_node_number = std::numeric_limits::max(), last_node_number = 0, file_format = 1, current_line = 0; if(!infile.good()) { AKANTU_DEBUG_ERROR("Cannot open file " << filename); } while(infile.good()) { std::getline(infile, line); current_line++; /// read the header if(line == "$MeshFormat") { std::getline(infile, line); /// the format line std::stringstream sstr(line); std::string version; sstr >> version; Int format; sstr >> format; if(format != 0) AKANTU_DEBUG_ERROR("This reader can only read ASCII files."); std::getline(infile, line); /// the end of block line current_line += 2; file_format = 2; } /// read all nodes if(line == "$Nodes" || line == "$NOD") { UInt nb_nodes; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_nodes; current_line++; Vector & nodes = const_cast &>(mesh.getNodes()); nodes.resize(nb_nodes); mesh.nb_global_nodes = nb_nodes; UInt index; Real coord[3]; UInt spatial_dimension = nodes.getNbComponent(); /// for each node, read the coordinates for(UInt i = 0; i < nb_nodes; ++i) { UInt offset = i * spatial_dimension; std::getline(infile, line); std::stringstream sstr_node(line); sstr_node >> index >> coord[0] >> coord[1] >> coord[2]; current_line++; first_node_number = std::min(first_node_number,index); last_node_number = std::max(last_node_number, index); /// read the coordinates for(UInt j = 0; j < spatial_dimension; ++j) nodes.values[offset + j] = coord[j]; } std::getline(infile, line); /// the end of block line } /// read all elements if(line == "$Elements" || line == "$ELM") { UInt nb_elements; std::getline(infile, line); std::stringstream sstr(line); sstr >> nb_elements; current_line++; Int index; UInt msh_type; ElementType akantu_type, akantu_type_old = _not_defined; Vector *connectivity = NULL; UInt node_per_element = 0; for(UInt i = 0; i < nb_elements; ++i) { std::getline(infile, line); std::stringstream sstr_elem(line); current_line++; sstr_elem >> index; sstr_elem >> msh_type; /// get the connectivity vector depending on the element type akantu_type = _msh_to_akantu_element_types[msh_type]; if(akantu_type == _not_defined) continue; if(akantu_type != akantu_type_old) { connectivity = mesh.getConnectivityPointer(akantu_type); connectivity->resize(0); node_per_element = connectivity->getNbComponent(); akantu_type_old = akantu_type; } /// read tags informations if(file_format == 2) { UInt nb_tags; sstr_elem >> nb_tags; for(UInt j = 0; j < nb_tags; ++j) { Int tag; sstr_elem >> tag; std::stringstream sstr_tag_name; sstr_tag_name << "tag_" << j; - Vector * data = mesh.getUIntDataPointer(akantu_type, sstr_tag_name.str()); + Vector * data = mesh.getUIntDataPointer(akantu_type, sstr_tag_name.str(), _not_ghost); data->push_back(tag); } } else if (file_format == 1) { Int tag; sstr_elem >> tag; //reg-phys std::string tag_name = "tag_0"; - Vector * data = mesh.getUIntDataPointer(akantu_type, tag_name); + Vector * data = mesh.getUIntDataPointer(akantu_type, tag_name, _not_ghost); data->push_back(tag); sstr_elem >> tag; //reg-elem tag_name = "tag_1"; - data = mesh.getUIntDataPointer(akantu_type, tag_name); + data = mesh.getUIntDataPointer(akantu_type, tag_name, _not_ghost); data->push_back(tag); sstr_elem >> tag; //number-of-nodes } UInt local_connect[node_per_element]; for(UInt j = 0; j < node_per_element; ++j) { UInt node_index; sstr_elem >> node_index; AKANTU_DEBUG_ASSERT(node_index <= last_node_number, "Node number not in range : line " << current_line); node_index -= first_node_number; local_connect[_read_order[akantu_type][j]] = node_index; } connectivity->push_back(local_connect); } std::getline(infile, line); /// the end of block line } if((line[0] == '$') && (line.find("End") == std::string::npos)) { AKANTU_DEBUG_WARNING("Unsuported block_kind " << line << " at line " << current_line); } } infile.close(); } /* -------------------------------------------------------------------------- */ void MeshIOMSH::write(const std::string & filename, const Mesh & mesh) { std::ofstream outfile; const Vector & nodes = mesh.getNodes(); outfile.open(filename.c_str()); outfile << "$MeshFormat" << std::endl; outfile << "2.1 0 8" << std::endl;; outfile << "$EndMeshFormat" << std::endl;; outfile << std::setprecision(std::numeric_limits::digits10); outfile << "$Nodes" << std::endl;; outfile << nodes.getSize() << std::endl;; outfile << std::uppercase; for(UInt i = 0; i < nodes.getSize(); ++i) { Int offset = i * nodes.getNbComponent(); outfile << i+1; for(UInt j = 0; j < nodes.getNbComponent(); ++j) { outfile << " " << nodes.values[offset + j]; } if(nodes.getNbComponent() == 2) outfile << " " << 0.; outfile << std::endl;; } outfile << std::nouppercase; outfile << "$EndNodes" << std::endl;; outfile << "$Elements" << std::endl;; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; Int nb_elements = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { - const Vector & connectivity = mesh.getConnectivity(*it); + const Vector & connectivity = mesh.getConnectivity(*it, _not_ghost); nb_elements += connectivity.getSize(); } outfile << nb_elements << std::endl; UInt element_idx = 1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; - const Vector & connectivity = mesh.getConnectivity(type); + const Vector & connectivity = mesh.getConnectivity(type, _not_ghost); for(UInt i = 0; i < connectivity.getSize(); ++i) { UInt offset = i * connectivity.getNbComponent(); outfile << element_idx << " " << _akantu_to_msh_element_types[type] << " 3 1 1 0"; /// \todo write the real data in the file for(UInt j = 0; j < connectivity.getNbComponent(); ++j) { outfile << " " << connectivity.values[offset + j] + 1; } outfile << std::endl; element_idx++; } } outfile << "$EndElements" << std::endl;; outfile.close(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/mesh_utils/mesh_partition.cc b/mesh_utils/mesh_partition.cc index 217786bbd..1d70d6027 100644 --- a/mesh_utils/mesh_partition.cc +++ b/mesh_utils/mesh_partition.cc @@ -1,307 +1,302 @@ /** * @file mesh_partition.cc * @author Nicolas Richart * @date Mon Aug 16 17:16:59 2010 * * @brief implementation of common part of all partitioner * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "mesh_partition.hh" #include "mesh_utils.hh" #include "aka_types.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshPartition::MeshPartition(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id) : Memory(memory_id), id("MeshPartitioner"), mesh(mesh), spatial_dimension(spatial_dimension) { AKANTU_DEBUG_IN(); - for(UInt type = _not_defined; type < _max_element_type; ++type) { - partitions[type] = NULL; - ghost_partitions[type] = NULL; - ghost_partitions_offset[type] = NULL; - } - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ MeshPartition::~MeshPartition() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * conversion in c++ of a the GENDUALMETIS (mesh.c) function wrote by George in * Metis (University of Minnesota) */ void MeshPartition::buildDualGraph(Vector & dxadj, Vector & dadjncy) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt magic_number[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; ElementType type_p1 = Mesh::getP1ElementType(type); nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); - conn_val[nb_good_types] = mesh.getConnectivity(type).values; - nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); + conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values; + nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); magic_number[nb_good_types] = Mesh::getNbNodesPerElement(Mesh::getFacetElementType(type_p1)); nb_good_types++; } // Vector node_offset; // Vector node_index; CSR node_to_elem; // MeshUtils::buildNode2Elements(mesh, node_offset, node_index); MeshUtils::buildNode2Elements(mesh, node_to_elem); // UInt * node_offset_val = node_offset.values; // UInt * node_index_val = node_index.values; UInt nb_total_element = 0; UInt nb_total_node_element = 0; for (UInt t = 0; t < nb_good_types; ++t) { nb_total_element += nb_element[t]; nb_total_node_element += nb_element[t]*nb_nodes_per_element_p1[t]; } dxadj.resize(nb_total_element + 1); Int * dxadj_val = dxadj.values; /// initialize the dxadj array for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) dxadj_val[linerized_el] = nb_nodes_per_element_p1[t]; /// convert the dxadj_val array in a csr one for (UInt i = 1; i < nb_total_element; ++i) dxadj_val[i] += dxadj_val[i-1]; for (UInt i = nb_total_element; i > 0; --i) dxadj_val[i] = dxadj_val[i-1]; dxadj_val[0] = 0; dadjncy.resize(2*dxadj_val[nb_total_element]); Int * dadjncy_val = dadjncy.values; /// weight map to determine adjacency unordered_map::type weight_map; // UInt index[200], weight[200]; /// key, value // UInt mask = (1 << 11) - 1; /// hash function // Int * mark = new Int[mask + 1]; /// collision detector // for (UInt i = 0; i < mask + 1; ++i) mark[i] = -1; for (UInt t = 0, linerized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { UInt el_offset = el*nb_nodes_per_element[t]; /// fill the weight map // UInt m = 0; for (UInt n = 0; n < nb_nodes_per_element_p1[t]; ++n) { UInt node = conn_val[t][el_offset + n]; CSR::iterator k; for (k = node_to_elem.rbegin(node); k != node_to_elem.rend(node); --k) { // for (UInt k = node_offset_val[node + 1] - 1; // k >= node_offset_val[node]; // --k) { UInt current_el = *k;//node_index_val[k]; if(current_el <= linerized_el) break; unordered_map::type::iterator it_w; it_w = weight_map.find(current_el); if(it_w == weight_map.end()) { weight_map[current_el] = 1; } else { it_w->second++; } // UInt mark_offset = current_el & mask; // Int current_mark = mark[mark_offset]; // if(current_mark == -1) { /// if element not in map // index[m] = current_el; // weight[m] = 1; // mark[mark_offset] = m++; // } else if (index[current_mark] == current_el) { /// if element already in map // weight[current_mark]++; // } else { /// if element already in map but collision in the keys // UInt i; // for (i = 0; i < m; ++i) { // if(index[i] == current_el) { // weight[i]++; // break; // } // } // if(i == m) { // index[m] = current_el; // weight[m++] = 1; // } // } } } /// each element with a weight of the size of a facet are adjacent unordered_map::type::iterator it_w; for(it_w = weight_map.begin(); it_w != weight_map.end(); ++it_w) { if(it_w->second == magic_number[t]) { UInt adjacent_el = it_w->first; UInt index_adj = dxadj_val[adjacent_el ]++; UInt index_lin = dxadj_val[linerized_el]++; dadjncy_val[index_lin] = adjacent_el; dadjncy_val[index_adj] = linerized_el; } } // for (UInt n = 0; n < m; ++n) { // if(weight[n] == magic_number[t]) { // UInt adjacent_el = index[n]; // dadjncy_val[dxadj_val[linerized_el]++] = adjacent_el; // dadjncy_val[dxadj_val[adjacent_el ]++] = linerized_el; // } // mark[index[n] & mask] = -1; // } weight_map.clear(); } } Int k_start = 0; for (UInt t = 0, linerized_el = 0, j = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linerized_el) { for (Int k = k_start; k < dxadj_val[linerized_el]; ++k, ++j) dadjncy_val[j] = dadjncy_val[k]; dxadj_val[linerized_el] = j; k_start += nb_nodes_per_element_p1[t]; } for (UInt i = nb_total_element; i > 0; --i) dxadj_val[i] = dxadj_val[i-1]; dxadj_val[0] = 0; // delete [] mark; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartition::fillPartitionInformations(const Mesh & mesh, const Int * linearized_partitions) { AKANTU_DEBUG_IN(); // Vector node_offset; // Vector node_index; CSR node_to_elem; // MeshUtils::buildNode2Elements(mesh, node_offset, node_index); MeshUtils::buildNode2Elements(mesh, node_to_elem); // UInt * node_offset_val = node_offset.values; // UInt * node_index_val = node_index.values; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt linearized_el = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); std::stringstream sstr; sstr << mesh.getID() << ":partition:" << type; std::stringstream sstr_gi; sstr_gi << mesh.getID() << ":ghost_partition_offset:" << type; std::stringstream sstr_g; sstr_g << mesh.getID() << ":ghost_partition:" << type; - partitions [type] = &(alloc(sstr.str(), nb_element, 1, 0)); - ghost_partitions_offset[type] = &(alloc(sstr_gi.str(), nb_element + 1, 1, 0)); - ghost_partitions [type] = &(alloc(sstr_g.str(), 0, 1, 0)); + partitions (type, _not_ghost) = &(alloc(sstr.str(), nb_element, 1, 0)); + ghost_partitions_offset(type, _ghost) = &(alloc(sstr_gi.str(), nb_element + 1, 1, 0)); + ghost_partitions (type, _ghost) = &(alloc(sstr_g.str(), 0, 1, 0)); - const Vector & connectivity = mesh.getConnectivity(type); + const Vector & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt part = linearized_partitions[linearized_el]; - partitions[type]->values[el] = part; + partitions(type, _not_ghost)->values[el] = part; std::list list_adj_part; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.values[el * nb_nodes_per_element + n]; CSR::iterator ne; // for (UInt ne = node_offset_val[node]; ne < node_offset_val[node + 1]; ++ne) { for (ne = node_to_elem.begin(node); ne != node_to_elem.end(node); ++ne) { UInt adj_el = *ne;//node_index_val[ne]; UInt adj_part = linearized_partitions[adj_el]; if(part != adj_part) { list_adj_part.push_back(adj_part); } } } list_adj_part.sort(); list_adj_part.unique(); for(std::list::iterator adj_it = list_adj_part.begin(); adj_it != list_adj_part.end(); ++adj_it) { - ghost_partitions[type]->push_back(*adj_it); - ghost_partitions_offset[type]->values[el]++; + ghost_partitions(type, _ghost)->push_back(*adj_it); + ghost_partitions_offset(type, _ghost)->values[el]++; } } /// convert the ghost_partitions_offset array in an offset array + Vector & ghost_partitions_offset_ptr = *ghost_partitions_offset(type, _ghost); for (UInt i = 1; i < nb_element; ++i) - ghost_partitions_offset[type]->values[i] += ghost_partitions_offset[type]->values[i-1]; + ghost_partitions_offset_ptr(i) += ghost_partitions_offset_ptr(i-1); for (UInt i = nb_element; i > 0; --i) - ghost_partitions_offset[type]->values[i] = ghost_partitions_offset[type]->values[i-1]; - ghost_partitions_offset[type]->values[0] = 0; + ghost_partitions_offset_ptr(i) = ghost_partitions_offset_ptr(i-1); + ghost_partitions_offset_ptr(0) = 0; } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/mesh_utils/mesh_partition.hh b/mesh_utils/mesh_partition.hh index d3f502611..dc526baa5 100644 --- a/mesh_utils/mesh_partition.hh +++ b/mesh_utils/mesh_partition.hh @@ -1,127 +1,124 @@ /** * @file mesh_partition.hh * @author Nicolas Richart * @date Thu Aug 12 16:24:40 2010 * * @brief tools to partitionate a mesh * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MESH_PARTITION_HH__ #define __AKANTU_MESH_PARTITION_HH__ /* -------------------------------------------------------------------------- */ #include "aka_memory.hh" #include "mesh.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ class MeshPartition : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MeshPartition(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id = 0); virtual ~MeshPartition(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void partitionate(UInt nb_part) = 0; virtual void reorder() = 0; /// function to print the contain of the class //virtual void printself(std::ostream & stream, int indent = 0) const = 0; protected: /// build the dual graph of the mesh, for all element of spatial_dimension void buildDualGraph(Vector & dxadj, Vector & dadjncy); /// fill the partitions array with a given linearized partition information void fillPartitionInformations(const Mesh & mesh, const Int * linearized_partitions); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Partition, partitions, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostPartition, - ghost_partitions, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostPartitionOffset, - ghost_partitions_offset, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Partition, partitions, UInt); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GhostPartition, ghost_partitions, UInt); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GhostPartitionOffset, ghost_partitions_offset, UInt); AKANTU_GET_MACRO(NbPartition, nb_partitions, UInt); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id std::string id; /// the mesh to partition const Mesh & mesh; /// dimension of the elements to consider in the mesh UInt spatial_dimension; /// number of partitions UInt nb_partitions; /// partition numbers ByElementTypeUInt partitions; ByElementTypeUInt ghost_partitions; - ByElementTypeUInt ghost_partitions_offset; Vector * permutation; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "mesh_partition_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const MeshPartition & _this) // { // _this.printself(stream); // return stream; // } __END_AKANTU__ #endif /* __AKANTU_MESH_PARTITION_HH__ */ diff --git a/mesh_utils/mesh_partition/mesh_partition_scotch.cc b/mesh_utils/mesh_partition/mesh_partition_scotch.cc index 847f55ab1..c7a97423f 100644 --- a/mesh_utils/mesh_partition/mesh_partition_scotch.cc +++ b/mesh_utils/mesh_partition/mesh_partition_scotch.cc @@ -1,470 +1,456 @@ /** * @file mesh_partition_scotch.cc * @author Nicolas Richart * @date Fri Aug 13 11:54:11 2010 * * @brief implementation of the MeshPartitionScotch class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "mesh_partition_scotch.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MeshPartitionScotch::MeshPartitionScotch(const Mesh & mesh, UInt spatial_dimension, const MemoryID & memory_id) : MeshPartition(mesh, spatial_dimension, memory_id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SCOTCH_Mesh * MeshPartitionScotch::createMesh() { AKANTU_DEBUG_IN(); UInt spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); UInt total_nb_element = 0; UInt nb_edge = 0; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); total_nb_element += nb_element; nb_edge += nb_element * nb_nodes_per_element; } SCOTCH_Num vnodbas = 0; SCOTCH_Num vnodnbr = nb_nodes; SCOTCH_Num velmbas = vnodnbr; SCOTCH_Num velmnbr = total_nb_element; SCOTCH_Num * verttab = new SCOTCH_Num[vnodnbr + velmnbr + 1]; SCOTCH_Num * vendtab = verttab + 1; SCOTCH_Num * velotab = NULL; SCOTCH_Num * vnlotab = NULL; SCOTCH_Num * vlbltab = NULL; memset(verttab, 0, (vnodnbr + velmnbr + 1) * sizeof(SCOTCH_Num)); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - const Vector & connectivity = mesh.getConnectivity(type); + const Vector & connectivity = mesh.getConnectivity(type, _not_ghost); /// count number of occurrence of each node for (UInt el = 0; el < nb_element; ++el) { UInt * conn_val = connectivity.values + el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { verttab[*(conn_val++)]++; } } } /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_nodes; ++i) verttab[i] += verttab[i-1]; for (UInt i = nb_nodes; i > 0; --i) verttab[i] = verttab[i-1]; verttab[0] = 0; /// rearrange element to get the node-element list SCOTCH_Num edgenbr = verttab[vnodnbr] + nb_edge; SCOTCH_Num * edgetab = new SCOTCH_Num[edgenbr]; UInt linearized_el = 0; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - const Vector & connectivity = mesh.getConnectivity(type); + const Vector & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el, ++linearized_el) { UInt * conn_val = connectivity.values + el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) edgetab[verttab[*(conn_val++)]++] = linearized_el + velmbas; } } for (UInt i = nb_nodes; i > 0; --i) verttab[i] = verttab[i-1]; verttab[0] = 0; SCOTCH_Num * verttab_tmp = verttab + vnodnbr + 1; SCOTCH_Num * edgetab_tmp = edgetab + verttab[vnodnbr]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - const Vector & connectivity = mesh.getConnectivity(type); + const Vector & connectivity = mesh.getConnectivity(type, _not_ghost); for (UInt el = 0; el < nb_element; ++el) { *verttab_tmp = *(verttab_tmp - 1) + nb_nodes_per_element; verttab_tmp++; UInt * conn = connectivity.values + el * nb_nodes_per_element; for (UInt i = 0; i < nb_nodes_per_element; ++i) { *(edgetab_tmp++) = *(conn++) + vnodbas; } } } SCOTCH_Mesh * meshptr = new SCOTCH_Mesh; SCOTCH_meshInit(meshptr); SCOTCH_meshBuild(meshptr, velmbas, vnodbas, velmnbr, vnodnbr, verttab, vendtab, velotab, vnlotab, vlbltab, edgenbr, edgetab); /// Check the mesh AKANTU_DEBUG_ASSERT(SCOTCH_meshCheck(meshptr) == 0, "Scotch mesh is not consistent"); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save initial graph FILE *fmesh = fopen("ScotchMesh.msh", "w"); SCOTCH_meshSave(meshptr, fmesh); fclose(fmesh); /// write geometry file std::ofstream fgeominit; fgeominit.open("ScotchMesh.xyz"); fgeominit << spatial_dimension << std::endl << nb_nodes << std::endl; const Vector & nodes = mesh.getNodes(); Real * nodes_val = nodes.values; for (UInt i = 0; i < nb_nodes; ++i) { fgeominit << i << " "; for (UInt s = 0; s < spatial_dimension; ++s) fgeominit << *(nodes_val++) << " "; fgeominit << std::endl;; } fgeominit.close(); } #endif AKANTU_DEBUG_OUT(); return meshptr; } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::destroyMesh(SCOTCH_Mesh * meshptr) { AKANTU_DEBUG_IN(); SCOTCH_Num velmbas, vnodbas, vnodnbr, velmnbr, *verttab, *vendtab, *velotab, *vnlotab, *vlbltab, edgenbr, *edgetab, degrptr; SCOTCH_meshData(meshptr, &velmbas, &vnodbas, &velmnbr, &vnodnbr, &verttab, &vendtab, &velotab, &vnlotab, &vlbltab, &edgenbr, &edgetab, °rptr); delete [] verttab; delete [] edgetab; SCOTCH_meshExit(meshptr); delete meshptr; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::partitionate(UInt nb_part) { AKANTU_DEBUG_IN(); nb_partitions = nb_part; AKANTU_DEBUG_INFO("Partitioning the mesh " << mesh.getID() << " in " << nb_part << " parts."); Vector dxadj; Vector dadjncy; buildDualGraph(dxadj, dadjncy); /// variables that will hold our structures in scotch format SCOTCH_Graph scotch_graph; SCOTCH_Strat scotch_strat; /// description number and arrays for struct mesh for scotch SCOTCH_Num baseval = 0; //base numbering for element and //nodes (0 -> C , 1 -> fortran) SCOTCH_Num vertnbr = dxadj.getSize() - 1; //number of vertexes SCOTCH_Num *parttab; //array of partitions SCOTCH_Num edgenbr = dxadj.values[vertnbr]; //twice the number of "edges" //(an "edge" bounds two nodes) SCOTCH_Num * verttab = dxadj.values; //array of start indices in edgetab SCOTCH_Num * vendtab = NULL; //array of after-last indices in edgetab SCOTCH_Num * velotab = NULL; //integer load associated with //every vertex ( optional ) SCOTCH_Num * edlotab = NULL; //integer load associated with //every edge ( optional ) SCOTCH_Num * edgetab = dadjncy.values; // adjacency array of every vertex SCOTCH_Num * vlbltab = NULL; // vertex label array (optional) /// Allocate space for Scotch arrays parttab = new SCOTCH_Num[vertnbr]; /// Initialize the strategy structure SCOTCH_stratInit (&scotch_strat); /// Initialize the graph structure SCOTCH_graphInit(&scotch_graph); /// Build the graph from the adjacency arrays SCOTCH_graphBuild(&scotch_graph, baseval, vertnbr, verttab, vendtab, velotab, vlbltab, edgenbr, edgetab, edlotab); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save initial graph FILE *fgraphinit = fopen("GraphIniFile.grf", "w"); SCOTCH_graphSave(&scotch_graph,fgraphinit); fclose(fgraphinit); /// write geometry file std::ofstream fgeominit; fgeominit.open("GeomIniFile.xyz"); fgeominit << spatial_dimension << std::endl << vertnbr << std::endl; const Vector & nodes = mesh.getNodes(); const Mesh::ConnectivityTypeList & f_type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator f_it; UInt out_linerized_el = 0; for(f_it = f_type_list.begin(); f_it != f_type_list.end(); ++f_it) { ElementType type = *f_it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(*f_it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); const Vector & connectivity = mesh.getConnectivity(type); Real mid[spatial_dimension] ; for (UInt el = 0; el < nb_element; ++el) { memset(mid, 0, spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt node = connectivity.values[nb_nodes_per_element * el + n]; for (UInt s = 0; s < spatial_dimension; ++s) mid[s] += ((Real) nodes.values[node * spatial_dimension + s]) / ((Real) nb_nodes_per_element); } fgeominit << out_linerized_el++ << " "; for (UInt s = 0; s < spatial_dimension; ++s) fgeominit << mid[s] << " "; fgeominit << std::endl;; } } fgeominit.close(); } #endif /// Check the graph AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0, "Graph to partition is not consistent"); /// Partition the mesh SCOTCH_graphPart(&scotch_graph, nb_part, &scotch_strat, parttab); /// Check the graph AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0, "Partitioned graph is not consistent"); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { /// save the partitioned graph FILE *fgraph=fopen("GraphFile.grf", "w"); SCOTCH_graphSave(&scotch_graph, fgraph); fclose(fgraph); /// save the partition map std::ofstream fmap; fmap.open("MapFile.map"); fmap << vertnbr << std::endl; for (Int i = 0; i < vertnbr; i++) fmap << i << " " << parttab[i] << std::endl; fmap.close(); } #endif /// free the scotch data structures SCOTCH_stratExit(&scotch_strat); SCOTCH_graphFree(&scotch_graph); SCOTCH_graphExit(&scotch_graph); fillPartitionInformations(mesh, parttab); delete [] parttab; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshPartitionScotch::reorder() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Reordering the mesh " << mesh.getID()); SCOTCH_Mesh * scotch_mesh = createMesh(); UInt nb_nodes = mesh.getNbNodes(); SCOTCH_Strat scotch_strat; // SCOTCH_Ordering scotch_order; SCOTCH_Num * permtab = new SCOTCH_Num[nb_nodes]; SCOTCH_Num * peritab = NULL; SCOTCH_Num cblknbr = 0; SCOTCH_Num * rangtab = NULL; SCOTCH_Num * treetab = NULL; /// Initialize the strategy structure SCOTCH_stratInit (&scotch_strat); SCOTCH_Graph scotch_graph; SCOTCH_graphInit(&scotch_graph); SCOTCH_meshGraph(scotch_mesh, &scotch_graph); #ifndef AKANTU_NDEBUG if (AKANTU_DEBUG_TEST(dblDump)) { FILE *fgraphinit = fopen("ScotchMesh.grf", "w"); SCOTCH_graphSave(&scotch_graph,fgraphinit); fclose(fgraphinit); } #endif /// Check the graph // AKANTU_DEBUG_ASSERT(SCOTCH_graphCheck(&scotch_graph) == 0, // "Mesh to Graph is not consistent"); SCOTCH_graphOrder(&scotch_graph, &scotch_strat, permtab, peritab, &cblknbr, rangtab, treetab); SCOTCH_graphExit(&scotch_graph); SCOTCH_stratExit(&scotch_strat); destroyMesh(scotch_mesh); /// Renumbering UInt spatial_dimension = mesh.getSpatialDimension(); - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - - for(it = type_list.begin(); it != type_list.end(); ++it) { - ElementType type = *it; - // if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; - - UInt nb_element = mesh.getNbElement(type); - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; - const Vector & connectivity = mesh.getConnectivity(type); + const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; - UInt * conn = connectivity.values; - for (UInt el = 0; el < nb_element * nb_nodes_per_element; ++el, ++conn) { - *conn = permtab[*conn]; - } - } - - const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost); - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - ElementType type = *it; - // if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; + for(it = type_list.begin(); it != type_list.end(); ++it) { + ElementType type = *it; - UInt nb_element = mesh.getNbElement(type,_ghost); - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); + UInt nb_element = mesh.getNbElement(type, gt); + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - const Vector & connectivity = mesh.getConnectivity(type,_ghost); + const Vector & connectivity = mesh.getConnectivity(type, gt); - UInt * conn = connectivity.values; - for (UInt el = 0; el < nb_element * nb_nodes_per_element; ++el, ++conn) { - *conn = permtab[*conn]; + UInt * conn = connectivity.values; + for (UInt el = 0; el < nb_element * nb_nodes_per_element; ++el, ++conn) { + *conn = permtab[*conn]; + } } } - /// \todo think of a in-place way to do it Real * new_coordinates = new Real[spatial_dimension * nb_nodes]; Real * old_coordinates = mesh.getNodes().values; for (UInt i = 0; i < nb_nodes; ++i) { memcpy(new_coordinates + permtab[i] * spatial_dimension, old_coordinates + i * spatial_dimension, spatial_dimension * sizeof(Real)); } memcpy(old_coordinates, new_coordinates, nb_nodes * spatial_dimension * sizeof(Real)); delete [] new_coordinates; delete [] permtab; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/mesh_utils/mesh_pbc.cc b/mesh_utils/mesh_pbc.cc index 8897efb4c..cfa8ae122 100644 --- a/mesh_utils/mesh_pbc.cc +++ b/mesh_utils/mesh_pbc.cc @@ -1,255 +1,260 @@ /** * @file mesh_pbc.cc * @author Guillaume Anciaux * @date Tue Feb 8 10:48:01 2011 * * @brief periodic boundary condition connectivity tweak * * @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 . * */ -#include "mesh_utils.hh" +/* -------------------------------------------------------------------------- */ #include +/* -------------------------------------------------------------------------- */ +#include "mesh_utils.hh" +/* -------------------------------------------------------------------------- */ + + __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /// class that sorts a set of nodes of same coordinates in 'dir' direction class CoordinatesComparison { public: - CoordinatesComparison (const UInt dimension, - const UInt dirx, const UInt diry, + CoordinatesComparison (const UInt dimension, + const UInt dirx, const UInt diry, Real * coords): dim(dimension),dir_x(dirx),dir_y(diry),coordinates(coords){} - + bool operator() (UInt n1, UInt n2){ Real p1_x = coordinates[dim*n1+dir_x]; Real p2_x = coordinates[dim*n2+dir_x]; Real diff_x = p1_x - p2_x; if (dim == 2 || fabs(diff_x) > Math::tolerance) return diff_x > 0.0 ? false : true; else if (dim > 2){ Real p1_y = coordinates[dim*n1+dir_y]; Real p2_y = coordinates[dim*n2+dir_y]; Real diff_y = p1_y - p2_y; return diff_y > 0 ? false : true; } return true; } private: UInt dim; UInt dir_x; UInt dir_y; Real * coordinates; }; /* -------------------------------------------------------------------------- */ // void MeshUtils::tweakConnectivityForPBC(Mesh & mesh, -// bool flag_x, -// bool flag_y, +// bool flag_x, +// bool flag_y, // bool flag_z){ // std::map pbc_pair; // mesh.computeBoundingBox(); // mesh.pbc_directions[0] = flag_x; // mesh.pbc_directions[1] = flag_y; // mesh.pbc_directions[2] = flag_z; // if (flag_x) computePBCMap(mesh,0,pbc_pair); // if (flag_y) computePBCMap(mesh,1,pbc_pair); // if (flag_z) computePBCMap(mesh,2,pbc_pair); // { // std::map::iterator it = pbc_pair.begin(); // std::map::iterator end = pbc_pair.end(); - + // Real * coords = mesh.nodes->values; // UInt dim = mesh.getSpatialDimension(); // while(it != end){ // UInt i1 = (*it).first; // UInt i2 = (*it).second; - -// AKANTU_DEBUG_INFO("pairing " << i1 << "(" -// << coords[dim*i1] << "," << coords[dim*i1+1] << "," + +// AKANTU_DEBUG_INFO("pairing " << i1 << "(" +// << coords[dim*i1] << "," << coords[dim*i1+1] << "," // << coords[dim*i1+2] // << ") with" -// << i2 << "(" -// << coords[dim*i2] << "," << coords[dim*i2+1] << "," +// << i2 << "(" +// << coords[dim*i2] << "," << coords[dim*i2+1] << "," // << coords[dim*i2+2] -// << ")"); +// << ")"); // ++it; // } // } // //allocate and initialize list of reversed elements // mesh.initByElementTypeUIntVector(mesh.reversed_elements_pbc,1,0,mesh.id,"reversed"); // // now loop over the elements to change the connectivity of some elements // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType type = *it; // UInt nb_elem = mesh.getNbElement(type); // UInt nb_nodes_per_elem = mesh.getNbNodesPerElement(type); // UInt * conn = mesh.getConnectivityPointer(type)->values; // UInt index = 0; // Vector & list = *(mesh.reversed_elements_pbc[type]); // for (UInt el = 0; el < nb_elem; el++) { // UInt flag_should_register_elem = false; // for (UInt k = 0; k < nb_nodes_per_elem; ++k,++index){ // if (pbc_pair.count(conn[index])){ // flag_should_register_elem = true; // AKANTU_DEBUG_INFO("elem list size " << list.getSize()); // AKANTU_DEBUG_INFO("node " << conn[index] +1 -// << " switch to " +// << " switch to " // << pbc_pair[conn[index]]+1); // // for (UInt toto = 0; toto < 3; ++toto) { // // AKANTU_DEBUG_INFO("dir " << toto << " coords " -// // << mesh.nodes->values[conn[index]*3+toto] -// // << " switch to " +// // << mesh.nodes->values[conn[index]*3+toto] +// // << " switch to " // // << mesh.nodes->values[pbc_pair[conn[index]]*3+toto]); // // } // std::stringstream str_temp; // str_temp << "initial elem(" << el << ") is "; // for (UInt l = 0 ; l < nb_nodes_per_elem ; ++ l){ // str_temp << conn[el*nb_nodes_per_elem+l]+1 << " "; // } // AKANTU_DEBUG_INFO(str_temp.str()); // conn[index] = pbc_pair[conn[index]]; -// } +// } // } // if (flag_should_register_elem) list.push_back(el); // } // } // } /* -------------------------------------------------------------------------- */ void MeshUtils::computePBCMap(const Mesh & mymesh,const UInt dir, std::map & pbc_pair){ std::vector selected_left; std::vector selected_right; Real * coords = mymesh.nodes->values; const UInt nb_nodes = mymesh.nodes->getSize(); const UInt dim = mymesh.getSpatialDimension(); if (dim <= dir) return; AKANTU_DEBUG_INFO("min " << mymesh.xmin[dir]); AKANTU_DEBUG_INFO("max " << mymesh.xmax[dir]); for (UInt i = 0; i < nb_nodes; ++i) { AKANTU_DEBUG_TRACE("treating " << coords[dim*i+dir]); if(Math::are_float_equal(coords[dim*i+dir],mymesh.xmin[dir])){ AKANTU_DEBUG_TRACE("pushing node " << i << " on the left side"); selected_left.push_back(i); } else if(Math::are_float_equal(coords[dim*i+dir],mymesh.xmax[dir])){ selected_right.push_back(i); AKANTU_DEBUG_TRACE("pushing node " << i << " on the right side"); } } - AKANTU_DEBUG_INFO("found " << selected_left.size() << " and " << selected_right.size() + AKANTU_DEBUG_INFO("found " << selected_left.size() << " and " << selected_right.size() << " nodes at each boundary for direction " << dir); UInt dir_x,dir_y; if (dim == 3){ if (dir == 0){ dir_x = 1;dir_y = 2; } else if (dir == 1){ dir_x = 0;dir_y = 2; } else if (dir == 2){ dir_x = 0;dir_y = 1; } } else if (dim == 2){ if (dir == 0){ dir_x = 1; } else if (dir == 1){ dir_x = 0; } } - + CoordinatesComparison compare_nodes(dim,dir_x,dir_y,coords); std::sort(selected_left.begin(),selected_left.end(),compare_nodes); std::sort(selected_right.begin(),selected_right.end(),compare_nodes); - + std::vector::iterator it_left = selected_left.begin(); std::vector::iterator end_left = selected_left.end(); std::vector::iterator it_right = selected_right.begin(); std::vector::iterator end_right = selected_right.end(); while ((it_left != end_left) && (it_right != end_right) ){ UInt i1 = *it_left; UInt i2 = *it_right; - AKANTU_DEBUG_TRACE("do I pair? " << i1 << "(" - << coords[dim*i1] << "," << coords[dim*i1+1] << "," + AKANTU_DEBUG_TRACE("do I pair? " << i1 << "(" + << coords[dim*i1] << "," << coords[dim*i1+1] << "," << coords[dim*i1+2] << ") with" - << i2 << "(" - << coords[dim*i2] << "," << coords[dim*i2+1] << "," + << i2 << "(" + << coords[dim*i2] << "," << coords[dim*i2+1] << "," << coords[dim*i2+2] - << ") in direction " << dir); + << ") in direction " << dir); + - Real dx = 0.0; Real dy = 0.0; if (dim == 2) dx = coords[dim*i1+dir_x] - coords[dim*i2+dir_x]; if (dim == 3) dy = coords[dim*i1+dir_y] - coords[dim*i2+dir_y]; - + if (fabs(dx*dx+dy*dy) < Math::tolerance) { //then i match these pairs if (pbc_pair.count(i2)){ i2 = pbc_pair[i2]; } pbc_pair[i1] = i2; - AKANTU_DEBUG_TRACE("pairing " << i1 << "(" - << coords[dim*i1] << "," << coords[dim*i1+1] << "," + AKANTU_DEBUG_TRACE("pairing " << i1 << "(" + << coords[dim*i1] << "," << coords[dim*i1+1] << "," << coords[dim*i1+2] << ") with" - << i2 << "(" - << coords[dim*i2] << "," << coords[dim*i2+1] << "," + << i2 << "(" + << coords[dim*i2] << "," << coords[dim*i2+1] << "," << coords[dim*i2+2] - << ") in direction " << dir); + << ") in direction " << dir); ++it_left; ++it_right; } else if (fabs(dy) < Math::tolerance && dx > 0) ++it_right; else if (fabs(dy) < Math::tolerance && dx < 0) ++it_left; else if (dy > 0) ++it_right; else if (dy < 0) ++it_left; else { - AKANTU_DEBUG_ERROR("this should not append"); + AKANTU_DEBUG_ERROR("this should not append"); } } AKANTU_DEBUG_INFO("found " << pbc_pair.size() << " pairs for direction " << dir); } __END_AKANTU__ diff --git a/mesh_utils/mesh_utils.cc b/mesh_utils/mesh_utils.cc index ab70c0dda..b727d5019 100644 --- a/mesh_utils/mesh_utils.cc +++ b/mesh_utils/mesh_utils.cc @@ -1,644 +1,646 @@ /** * @file mesh_utils.cc * @author Guillaume ANCIAUX * @date Wed Aug 18 14:21:00 2010 * * @brief All mesh utils necessary for various tasks * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "mesh_utils.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2Elements(const Mesh & mesh, CSR & node_to_elem, UInt spatial_dimension) { AKANTU_DEBUG_IN(); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); UInt nb_nodes = mesh.getNbNodes(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; // UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; // ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = Mesh::getNbNodesPerElement(type); // type_p1 = Mesh::getP1ElementType(type); // nb_nodes_per_element_p1[nb_good_types] = Mesh::getNbNodesPerElement(type_p1); - conn_val[nb_good_types] = mesh.getConnectivity(type).values; - nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); + conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values; + nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); nb_good_types++; } AKANTU_DEBUG_ASSERT(nb_good_types != 0, "Some elements must be found in right dimension to compute facets!"); /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); // node_offset.resize(nb_nodes + 1); // UInt * node_offset_val = node_offset.values; /// count number of occurrence of each node // memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); for (UInt t = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) { ++node_to_elem.rowOffset(conn_val[t][el_offset + n]); // node_offset_val[conn_val[t][el_offset + n]]++; } } } // /// convert the occurrence array in a csr one // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// rearrange element to get the node-element list // node_to_elem.resize(node_offset_val[nb_nodes]); // UInt * node_to_elem_val = node_to_elem.values; for (UInt t = 0, linearized_el = 0; t < nb_good_types; ++t) for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt n = 0; n < nb_nodes_per_element[t]; ++n) node_to_elem.insertInRow(conn_val[t][el_offset + n], linearized_el); // node_to_elem_val[node_offset_val[conn_val[t][el_offset + n]]++] = linearized_el; } node_to_elem.endInsertions(); // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNode2ElementsByElementType(const Mesh & mesh, ElementType type, CSR & node_to_elem) { // Vector & node_offset, // Vector & node_to_elem) { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_elements = mesh.getConnectivity(type).getSize(); + UInt nb_elements = mesh.getConnectivity(type, _not_ghost).getSize(); - UInt * conn_val = mesh.getConnectivity(type).values; + UInt * conn_val = mesh.getConnectivity(type, _not_ghost).values; /// array for the node-element list node_to_elem.resizeRows(nb_nodes); node_to_elem.clearRows(); // node_offset.resize(nb_nodes + 1); // UInt * node_offset_val = node_offset.values; // memset(node_offset_val, 0, (nb_nodes + 1)*sizeof(UInt)); /// count number of occurrence of each node for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) ++node_to_elem.rowOffset(conn_val[el_offset + n]); // node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; } /// convert the occurrence array in a csr one // for (UInt i = 1; i < nb_nodes; ++i) node_offset_val[i] += node_offset_val[i-1]; // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.countToCSR(); node_to_elem.resizeCols(); node_to_elem.beginInsertions(); /// save the element index in the node-element list // node_to_elem.resize(node_offset_val[nb_nodes]); // UInt * node_to_elem_val = node_to_elem.values; for (UInt el = 0; el < nb_elements; ++el) { UInt el_offset = el*nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { node_to_elem.insertInRow(conn_val[el_offset + n], el); } // node_to_elem_val[node_offset_val[conn_val[nb_nodes_per_element*el + n]]] = el; // node_offset_val[conn_val[nb_nodes_per_element*el + n]]++; } // /// rearrange node_offset to start with 0 // for (UInt i = nb_nodes; i > 0; --i) node_offset_val[i] = node_offset_val[i-1]; // node_offset_val[0] = 0; node_to_elem.endInsertions(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildFacets(Mesh & mesh, bool boundary_flag, bool internal_flag){ AKANTU_DEBUG_IN(); CSR node_to_elem; // Vector node_offset; // Vector node_to_elem; // buildNode2Elements(mesh,node_offset,node_to_elem); buildNode2Elements(mesh, node_to_elem); // std::cout << "node offset " << std::endl << node_offset << std::endl; // std::cout << "node to elem " << std::endl << node_to_elem << std::endl; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); UInt nb_good_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_facet[nb_types]; UInt nb_facets[nb_types]; UInt ** node_in_facet[nb_types]; Vector * connectivity_facets[nb_types]; Vector * connectivity_internal_facets[nb_types]; UInt * conn_val[nb_types]; UInt nb_element[nb_types]; ElementType facet_type; Mesh * internal_facets_mesh = NULL; UInt spatial_dimension = mesh.getSpatialDimension(); if (internal_flag) internal_facets_mesh = mesh.getInternalFacetsMeshPointer(); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) != spatial_dimension) continue; nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); facet_type = mesh.getFacetElementType(type); nb_facets[nb_good_types] = mesh.getNbFacetsPerElement(type); node_in_facet[nb_good_types] = mesh.getFacetLocalConnectivity(type); nb_nodes_per_facet[nb_good_types] = mesh.getNbNodesPerElement(facet_type); if (boundary_flag){ // getting connectivity of boundary facets connectivity_facets[nb_good_types] = mesh.getConnectivityPointer(facet_type); connectivity_facets[nb_good_types]->resize(0); } if (internal_flag){ // getting connectivity of internal facets connectivity_internal_facets[nb_good_types] = internal_facets_mesh->getConnectivityPointer(facet_type); connectivity_internal_facets[nb_good_types]->resize(0); } - conn_val[nb_good_types] = mesh.getConnectivity(type).values; - nb_element[nb_good_types] = mesh.getConnectivity(type).getSize(); + conn_val[nb_good_types] = mesh.getConnectivity(type, _not_ghost).values; + nb_element[nb_good_types] = mesh.getConnectivity(type, _not_ghost).getSize(); nb_good_types++; } Vector counter; /// count number of occurrence of each node for (UInt t = 0,linearized_el = 0; t < nb_good_types; ++t) { for (UInt el = 0; el < nb_element[t]; ++el, ++linearized_el) { UInt el_offset = el*nb_nodes_per_element[t]; for (UInt f = 0; f < nb_facets[t]; ++f) { //build the nodes involved in facet 'f' UInt facet_nodes[nb_nodes_per_facet[t]]; for (UInt n = 0; n < nb_nodes_per_facet[t]; ++n) { UInt node_facet = node_in_facet[t][f][n]; facet_nodes[n] = conn_val[t][el_offset + node_facet]; } //our reference is the first node CSR::iterator first_node_elements; //UInt * first_node_elements = node_to_elem.values+node_offset.values[facet_nodes[0]]; UInt first_node_nelements = node_to_elem.getNbCols(facet_nodes[0]); // node_offset.values[facet_nodes[0]+1]- // node_offset.values[facet_nodes[0]]; counter.resize(first_node_nelements); counter.clear(); //loop over the other nodes to search intersecting elements for (UInt n = 1; n < nb_nodes_per_facet[t]; ++n) { first_node_elements = node_to_elem.begin(facet_nodes[0]); CSR::iterator node_elements, node_elements_begin, node_elements_end; node_elements_begin = node_to_elem.begin(facet_nodes[n]); node_elements_end = node_to_elem.end(facet_nodes[n]); // UInt * node_elements = node_to_elem.values+node_offset.values[facet_nodes[n]]; // node_offset.values[facet_nodes[n]+1]- // node_offset.values[facet_nodes[n]]; for (UInt el1 = 0; el1 < first_node_nelements; ++el1, ++first_node_elements) { for (node_elements = node_elements_begin; node_elements != node_elements_end; ++node_elements) { if (*first_node_elements == *node_elements) { ++counter.values[el1]; break; } } if (counter.values[el1] == nb_nodes_per_facet[t]) break; } } bool connected_facet = false; //the connected elements are those for which counter is n_facet // UInt connected_element = -1; for (UInt el1 = 0; el1 < counter.getSize(); el1++) { UInt el_index = node_to_elem(facet_nodes[0], el1); // node_to_elem.values[node_offset.values[facet_nodes[0]]+el1]; if (counter.values[el1] == nb_nodes_per_facet[t]-1 && el_index > linearized_el){ // connected_element = el_index; AKANTU_DEBUG(dblDump,"connecting elements " << linearized_el << " and " << el_index); if (internal_flag) connectivity_internal_facets[t]->push_back(facet_nodes); } if (counter.values[el1] == nb_nodes_per_facet[t]-1 && el_index != linearized_el) connected_facet = true; } if (!connected_facet) { AKANTU_DEBUG(dblDump,"facet " << f << " in element " << linearized_el << " is a boundary"); if (boundary_flag) connectivity_facets[t]->push_back(facet_nodes); } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ // void MeshUtils::buildNormals(Mesh & mesh,UInt spatial_dimension){ // AKANTU_DEBUG_IN(); // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // Mesh::ConnectivityTypeList::const_iterator it; // UInt nb_types = type_list.size(); // UInt nb_nodes_per_element[nb_types]; // UInt nb_nodes_per_element_p1[nb_types]; // UInt nb_good_types = 0; // Vector * connectivity[nb_types]; // Vector * normals[nb_types]; // if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType type = *it; // ElementType type_p1 = mesh.getP1ElementType(type); // if(mesh.getSpatialDimension(type) != spatial_dimension) continue; // nb_nodes_per_element[nb_good_types] = mesh.getNbNodesPerElement(type); // nb_nodes_per_element_p1[nb_good_types] = mesh.getNbNodesPerElement(type_p1); // // getting connectivity // connectivity[nb_good_types] = mesh.getConnectivityPointer(type); // if (!connectivity[nb_good_types]) // AKANTU_DEBUG_ERROR("connectivity is not allocatted : this should probably not have happened"); // //getting array of normals // normals[nb_good_types] = mesh.getNormalsPointer(type); // if(normals[nb_good_types]) // normals[nb_good_types]->resize(0); // else // normals[nb_good_types] = &mesh.createNormals(type); // nb_good_types++; // } // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void MeshUtils::renumberMeshNodes(Mesh & mesh, UInt * local_connectivities, UInt nb_local_element, UInt nb_ghost_element, ElementType type, Vector & nodes_numbers) { AKANTU_DEBUG_IN(); nodes_numbers.resize(0); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt * conn = local_connectivities; std::map renumbering_map; /// renumber the nodes for (UInt el = 0; el < nb_local_element + nb_ghost_element; ++el) { for (UInt n = 0; n < nb_nodes_per_element; ++n) { std::map::iterator it = renumbering_map.find(*conn); // Int nn = nodes_numbers.find(*conn); if(it == renumbering_map.end()) { UInt old_node = *conn; nodes_numbers.push_back(old_node); *conn = nodes_numbers.getSize() - 1; renumbering_map[old_node] = *conn; } else { *conn = it->second; } conn++; } } renumbering_map.clear(); /// copy the renumbered connectivity to the right place Vector * local_conn = mesh.getConnectivityPointer(type); local_conn->resize(nb_local_element); memcpy(local_conn->values, local_connectivities, nb_local_element * nb_nodes_per_element * sizeof(UInt)); Vector * ghost_conn = mesh.getConnectivityPointer(type,_ghost); ghost_conn->resize(nb_ghost_element); memcpy(ghost_conn->values, local_connectivities + nb_local_element * nb_nodes_per_element, nb_ghost_element * nb_nodes_per_element * sizeof(UInt)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::setUIntData(Mesh & mesh, UInt * data, UInt nb_tags, const ElementType & type) { AKANTU_DEBUG_IN(); - UInt nb_element = mesh.getNbElement(type); - UInt nb_ghost_element = mesh.getNbElement(type,_ghost); + UInt nb_element = mesh.getNbElement(type, _not_ghost); + UInt nb_ghost_element = mesh.getNbElement(type, _ghost); char * names = reinterpret_cast(data + (nb_element + nb_ghost_element) * nb_tags); - Mesh::UIntDataMap & uint_data_map = mesh.getUIntDataMap(type); - Mesh::UIntDataMap & ghost_uint_data_map = mesh.getUIntDataMap(type,_ghost); + UIntDataMap & uint_data_map = mesh.getUIntDataMap(type, _not_ghost); + UIntDataMap & ghost_uint_data_map = mesh.getUIntDataMap(type, _ghost); for (UInt t = 0; t < nb_tags; ++t) { std::string name(names); // std::cout << name << std::endl; names += name.size() + 1; - - Mesh::UIntDataMap::iterator it = uint_data_map.find(name); + UIntDataMap::iterator it = uint_data_map.find(name); if(it == uint_data_map.end()) { uint_data_map[name] = new Vector(0, 1, name); it = uint_data_map.find(name); } it->second->resize(nb_element); memcpy(it->second->values, data, nb_element * sizeof(UInt)); data += nb_element; it = ghost_uint_data_map.find(name); if(it == ghost_uint_data_map.end()) { ghost_uint_data_map[name] = new Vector(0, 1, name); it = ghost_uint_data_map.find(name); } it->second->resize(nb_ghost_element); memcpy(it->second->values, data, nb_ghost_element * sizeof(UInt)); data += nb_ghost_element; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildSurfaceID(Mesh & mesh) { AKANTU_DEBUG_IN(); // Vector node_offset; // Vector node_to_elem; + CSR node_to_elem; + /// Get list of surface elements UInt spatial_dimension = mesh.getSpatialDimension(); + // buildNode2Elements(mesh, node_offset, node_to_elem, spatial_dimension-1); buildNode2Elements(mesh, node_to_elem, spatial_dimension-1); - /// Find which types of elements have been linearized const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_types = type_list.size(); ElementType lin_element_type[nb_types]; UInt nb_lin_types = 0; UInt nb_nodes_per_element[nb_types]; UInt nb_nodes_per_element_p1[nb_types]; UInt * conn_val[nb_types]; - UInt nb_element[nb_types]; + UInt nb_element[nb_types+1]; ElementType type_p1; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != spatial_dimension) continue; ElementType facet_type = mesh.getFacetElementType(type); lin_element_type[nb_lin_types] = facet_type; nb_nodes_per_element[nb_lin_types] = Mesh::getNbNodesPerElement(facet_type); type_p1 = Mesh::getP1ElementType(facet_type); nb_nodes_per_element_p1[nb_lin_types] = Mesh::getNbNodesPerElement(type_p1); - conn_val[nb_lin_types] = mesh.getConnectivity(facet_type).values; - nb_element[nb_lin_types] = mesh.getConnectivity(facet_type).getSize(); + conn_val[nb_lin_types] = mesh.getConnectivity(facet_type, _not_ghost).values; + nb_element[nb_lin_types] = mesh.getNbElement(facet_type, _not_ghost); nb_lin_types++; } for (UInt i = 1; i < nb_lin_types; ++i) nb_element[i] += nb_element[i+1]; for (UInt i = nb_lin_types; i > 0; --i) nb_element[i] = nb_element[i-1]; nb_element[0] = 0; /// Find close surfaces Vector surface_value_id(1, nb_element[nb_lin_types], -1); Int * surf_val = surface_value_id.values; UInt nb_surfaces = 0; UInt nb_cecked_elements; UInt nb_elements_to_ceck; UInt * elements_to_ceck = new UInt [nb_element[nb_lin_types]]; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); for (UInt lin_el = 0; lin_el < nb_element[nb_lin_types]; ++lin_el) { if(surf_val[lin_el] != -1) continue; /* Surface id already assigned */ /* First element of new surface */ surf_val[lin_el] = nb_surfaces; nb_cecked_elements = 0; nb_elements_to_ceck = 1; memset(elements_to_ceck, 0, nb_element[nb_lin_types]*sizeof(UInt)); elements_to_ceck[0] = lin_el; // Find others elements belonging to this surface while(nb_cecked_elements < nb_elements_to_ceck) { UInt ceck_lin_el = elements_to_ceck[nb_cecked_elements]; // Transform linearized index of element into ElementType one UInt lin_type_nb = 0; while (ceck_lin_el >= nb_element[lin_type_nb+1]) lin_type_nb++; UInt ceck_el = ceck_lin_el - nb_element[lin_type_nb]; // Get connected elements UInt el_offset = ceck_el*nb_nodes_per_element[lin_type_nb]; for (UInt n = 0; n < nb_nodes_per_element_p1[lin_type_nb]; ++n) { UInt node_id = conn_val[lin_type_nb][el_offset + n]; CSR::iterator it_n; for (it_n = node_to_elem.begin(node_id); it_n != node_to_elem.end(node_id); ++it_n) { // for (UInt i = node_offset.values[node_id]; i < node_offset.values[node_id+1]; ++i) { if(surf_val[*it_n] == -1) { /* Found new surface element */ surf_val[*it_n] = nb_surfaces; elements_to_ceck[nb_elements_to_ceck] = *it_n; nb_elements_to_ceck++; } // if(surf_val[node_to_elem.values[i]] == -1) { /* Found new surface element */ // surf_val[node_to_elem.values[i]] = nb_surfaces; // elements_to_ceck[nb_elements_to_ceck] = node_to_elem.values[i]; // nb_elements_to_ceck++; // } } } nb_cecked_elements++; } nb_surfaces++; } delete [] elements_to_ceck; /// Transform local linearized element index in the global one for (UInt i = 0; i < nb_lin_types; ++i) nb_element[i] = nb_element[i+1] - nb_element[i]; UInt el_offset = 0; for (UInt type_it = 0; type_it < nb_lin_types; ++type_it) { ElementType type = lin_element_type[type_it]; - Vector * surf_id_type = mesh.getSurfaceIdPointer(type); + Vector * surf_id_type = mesh.getSurfaceIDPointer(type, _not_ghost); surf_id_type->resize(nb_element[type_it]); + surf_id_type->clear(); for (UInt el = 0; el < nb_element[type_it]; ++el) surf_id_type->values[el] = surf_val[el+el_offset]; el_offset += nb_element[type_it]; } /// Set nb_surfaces in mesh mesh.nb_surfaces = nb_surfaces; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MeshUtils::buildNodesPerSurface(const Mesh & mesh, CSR & nodes_per_surface) { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_nodes = mesh.getNbNodes(); UInt spatial_dimension = mesh.getSpatialDimension(); //surface elements UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(mesh.getSpatialDimension(*it) != spatial_dimension) continue; facet_type[nb_facet_types++] = mesh.getFacetElementType(*it); } UInt * surface_nodes_id = new UInt[nb_nodes*nb_surfaces]; std::fill_n(surface_nodes_id, nb_surfaces*nb_nodes, 0); for(UInt t = 0; t < nb_facet_types; ++t) { ElementType type = facet_type[t]; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_per_element = mesh.getNbNodesPerElement(type); - UInt * connecticity = mesh.getConnectivity(type).values; - UInt * surface_id = mesh.getSurfaceId(type).values;; + UInt * connecticity = mesh.getConnectivity(type, _not_ghost).values; + UInt * surface_id = mesh.getSurfaceID(type, _not_ghost).values;; for (UInt el = 0; el < nb_element; ++el) { UInt offset = *surface_id * nb_nodes; for (UInt n = 0; n < nb_nodes_per_element; ++n) { surface_nodes_id[offset + *connecticity] = 1; ++connecticity; } ++surface_id; } } nodes_per_surface.resizeRows(nb_surfaces); nodes_per_surface.clearRows(); UInt * surface_nodes_id_tmp = surface_nodes_id; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = 0; n < nb_nodes; ++n) nodes_per_surface.rowOffset(s) += *surface_nodes_id_tmp++; nodes_per_surface.countToCSR(); nodes_per_surface.resizeCols(); nodes_per_surface.beginInsertions(); surface_nodes_id_tmp = surface_nodes_id; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = 0; n < nb_nodes; ++n) { if (*surface_nodes_id_tmp == 1) nodes_per_surface.insertInRow(s, n); surface_nodes_id_tmp++; } nodes_per_surface.endInsertions(); delete [] surface_nodes_id; AKANTU_DEBUG_OUT(); } __END_AKANTU__ // LocalWords: ElementType diff --git a/model/heat_transfer/heat_transfer_model.cc b/model/heat_transfer/heat_transfer_model.cc index d66b59b8d..dedf5d579 100644 --- a/model/heat_transfer/heat_transfer_model.cc +++ b/model/heat_transfer/heat_transfer_model.cc @@ -1,519 +1,481 @@ /** * @file heat_transfer_model.cc * @author Rui WANG * @author Guillaume Anciaux * @author Nicolas Richart * @date Fri May 4 13:46:43 2011 * * @brief Implementation of HeatTransferModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ +#include "aka_common.hh" #include "heat_transfer_model.hh" #include "aka_math.hh" #include "aka_common.hh" #include "fem_template.hh" #include "mesh.hh" #include "static_communicator.hh" #include "parser.hh" #include "generalized_trapezoidal.hh" // #include "sparse_matrix.hh" // #include "solver.hh" // #ifdef AKANTU_USE_MUMPS // #include "solver_mumps.hh" // #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ HeatTransferModel::HeatTransferModel(Mesh & mesh, UInt dim, const ModelID & id, - const MemoryID & memory_id): + const MemoryID & memory_id) : Model(id, memory_id), integrator(new ForwardEuler()), - spatial_dimension(dim) -{ + spatial_dimension(dim) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); - registerFEMObject("HeatTransferFEM",mesh,spatial_dimension); + + std::stringstream sstr; sstr << id << ":fem"; + registerFEMObject(sstr.str(), mesh,spatial_dimension); this->temperature= NULL; - for (UInt t = _not_defined; t < _max_element_type; ++t) { - this->temperature_gradient[t] = NULL; - this->temperature_gradient_ghost[t] = NULL; - } - this->heat_flux = NULL; - this->boundary = NULL; + this->residual = NULL; + this->boundary = NULL; - AKANTU_DEBUG_OUT(); + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void HeatTransferModel::initModel() -{ +void HeatTransferModel::initModel() { getFEM().initShapeFunctions(_not_ghost); getFEM().initShapeFunctions(_ghost); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_capacity); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_temperature); synch_registry->registerSynchronizer(synch_parallel, _gst_htm_gradient_temperature); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initPBC(UInt x, UInt y, UInt z) { AKANTU_DEBUG_IN(); Model::initPBC(x,y,z); PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair); synch_registry->registerSynchronizer(*synch, _gst_htm_capacity); synch_registry->registerSynchronizer(*synch, _gst_htm_temperature); changeLocalEquationNumberforPBC(pbc_pair,1); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::initVectors() { AKANTU_DEBUG_IN(); UInt nb_nodes = getFEM().getMesh().getNbNodes(); std::stringstream sstr_temp; sstr_temp << id << ":temperature"; std::stringstream sstr_temp_rate; sstr_temp << id << ":temperature_rate"; std::stringstream sstr_inc; sstr_temp_rate<< id << ":increment"; std::stringstream sstr_residual; sstr_residual << id << ":residual"; std::stringstream sstr_lump; sstr_lump << id << ":lumped"; std::stringstream sstr_boun; sstr_boun << id << ":boundary"; temperature = &(alloc(sstr_temp.str(), nb_nodes, 1, REAL_INIT_VALUE)); temperature_rate = &(alloc(sstr_temp_rate.str(), nb_nodes, 1, REAL_INIT_VALUE)); increment = &(alloc(sstr_inc.str(), nb_nodes, 1, REAL_INIT_VALUE)); residual = &(alloc(sstr_residual.str(), nb_nodes, 1, REAL_INIT_VALUE)); capacity_lumped = &(alloc(sstr_lump.str(), nb_nodes, 1, REAL_INIT_VALUE)); boundary = &(alloc(sstr_boun.str(), nb_nodes, 1, false)); Mesh::ConnectivityTypeList::const_iterator it; /* -------------------------------------------------------------------------- */ // not ghost - getFEM().getMesh().initByElementTypeRealVector(temperature_gradient, - spatial_dimension, - spatial_dimension, - id,"temperatureGradient", - _not_ghost); + getFEM().getMesh().initByElementTypeVector(temperature_gradient, + spatial_dimension, + spatial_dimension, + id,"temperature_gradient"); - const Mesh::ConnectivityTypeList & type_list = - getFEM().getMesh().getConnectivityTypeList(_not_ghost); - - for(it = type_list.begin(); it != type_list.end(); ++it) - { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - UInt nb_element = getFEM().getMesh().getNbElement(*it); - UInt nb_quad_points = this->getFEM().getNbQuadraturePoints(*it) * nb_element; - temperature_gradient[*it]->resize(nb_quad_points); - temperature_gradient[*it]->clear(); - } - /* ------------------------------------------------------------------------ */ - // ghost - getFEM().getMesh().initByElementTypeRealVector(temperature_gradient_ghost, - spatial_dimension, - spatial_dimension, - id,"temperatureGradient", - _ghost); + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; - const Mesh::ConnectivityTypeList & type_list_ghost = - getFEM().getMesh().getConnectivityTypeList(_ghost); + const Mesh::ConnectivityTypeList & type_list = + getFEM().getMesh().getConnectivityTypeList(gt); - for(it = type_list_ghost.begin(); it != type_list_ghost.end(); ++it) - { + for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - UInt nb_element = getFEM().getMesh().getNbElement(*it,_ghost); - UInt nb_quad_points = this->getFEM().getNbQuadraturePoints(*it) * nb_element; - temperature_gradient_ghost[*it]->resize(nb_quad_points); - temperature_gradient_ghost[*it]->clear(); + UInt nb_element = getFEM().getMesh().getNbElement(*it, gt); + UInt nb_quad_points = this->getFEM().getNbQuadraturePoints(*it, gt) * nb_element; + temperature_gradient(*it, gt)->resize(nb_quad_points); + temperature_gradient(*it, gt)->clear(); } - /* -------------------------------------------------------------------------- */ + } + /* -------------------------------------------------------------------------- */ dof_synchronizer = new DOFSynchronizer(getFEM().getMesh(),1); dof_synchronizer->initLocalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ HeatTransferModel::~HeatTransferModel() { AKANTU_DEBUG_IN(); delete [] conductivity; if(dof_synchronizer) delete dof_synchronizer; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); FEM & fem = getFEM(); const Mesh::ConnectivityTypeList & type_list = fem.getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_element = getFEM().getMesh().getNbElement(*it,ghost_type); - UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it); + UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it, ghost_type); Vector rho_1 (nb_element * nb_quadrature_points,1, capacity * density); fem.assembleFieldLumped(rho_1,1,*capacity_lumped, dof_synchronizer->getLocalDOFEquationNumbers(), *it, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::assembleCapacityLumped() { AKANTU_DEBUG_IN(); capacity_lumped->clear(); assembleCapacityLumped(_not_ghost); assembleCapacityLumped(_ghost); getSynchronizerRegistry().synchronize(akantu::_gst_htm_capacity); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual() { AKANTU_DEBUG_IN(); /// @f$ r = q_{ext} - q_{int} - C \dot T @f$ // start synchronization synch_registry->asynchronousSynchronize(_gst_htm_temperature); // finalize communications synch_registry->waitEndSynchronize(_gst_htm_temperature); //clear the array /// first @f$ r = q_{ext} @f$ residual->clear(); /// then @f$ r -= q_{int} @f$ // update the not ghost ones updateResidual(_not_ghost); // update for the received ghosts updateResidual(_ghost); /// finally @f$ r -= C \dot T @f$ // lumped C UInt nb_nodes = temperature_rate->getSize(); UInt nb_degre_of_freedom = temperature_rate->getNbComponent(); Real * capacity_val = capacity_lumped->values; Real * temp_rate_val = temperature_rate->values; Real * res_val = residual->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n) { if(!(*boundary_val)) { *res_val -= *capacity_val * *temp_rate_val; } boundary_val++; res_val++; capacity_val++; temp_rate_val++; } #ifndef AKANTU_NDEBUG getSynchronizerRegistry().synchronize(akantu::_gst_htm_gradient_temperature); #endif AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::updateResidual(const GhostType & ghost_type) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = this->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; const Vector & shapes_derivatives = getFEM().getShapesDerivatives(*it,ghost_type); UInt nb_element = getFEM().getMesh().getNbElement(*it,ghost_type); - Real * gT_val = NULL; - if(ghost_type == _not_ghost) { - for (UInt i = 0; i < getFEM().getMesh().getNbElement(*it,_not_ghost) ; ++i) { - for (UInt j = 0; j < spatial_dimension; ++j) { - temperature_gradient[*it]->values[spatial_dimension*i+j] = 0; - } - } - this->getFEM().gradientOnQuadraturePoints(*temperature, - *temperature_gradient[*it], - 1 ,*it); - gT_val = temperature_gradient[*it]->values; - } - else { - for (UInt i = 0; i < getFEM().getMesh().getNbElement(*it,_ghost) ; ++i) { - for (UInt j = 0; j < spatial_dimension; ++j) { - temperature_gradient_ghost[*it]->values[spatial_dimension*i+j] = 3e9; - } - } - this->getFEM().gradientOnQuadraturePoints(*temperature, - *temperature_gradient_ghost[*it], - 1 ,*it,_ghost); - gT_val = temperature_gradient_ghost[*it]->values; - } + this->getFEM().gradientOnQuadraturePoints(*temperature, + *temperature_gradient(*it, ghost_type), + 1 ,*it); + Real * gT_val = temperature_gradient(*it, ghost_type)->values; + - UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it); + UInt nb_quadrature_points = getFEM().getNbQuadraturePoints(*it, ghost_type); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); Real * k_gT_val = new Real[spatial_dimension]; Real * shapes_derivatives_val = shapes_derivatives.values; UInt bt_k_gT_size = nb_nodes_per_element; Vector * bt_k_gT = new Vector (nb_quadrature_points*nb_element, bt_k_gT_size); Real * bt_k_gT_val = bt_k_gT->values; for (UInt el = 0; el < nb_element; ++el) { for (UInt i = 0; i < nb_quadrature_points; ++i) { Math::matrixt_vector(spatial_dimension, spatial_dimension, conductivity, gT_val, k_gT_val); gT_val += spatial_dimension; Math::matrix_vector(nb_nodes_per_element, spatial_dimension, shapes_derivatives_val, k_gT_val, bt_k_gT_val); shapes_derivatives_val += nb_nodes_per_element * spatial_dimension; bt_k_gT_val += bt_k_gT_size; } } Vector * q_e = new Vector(0,bt_k_gT_size,"q_e"); this->getFEM().integrate(*bt_k_gT, *q_e, bt_k_gT_size, *it,ghost_type); delete bt_k_gT; this->getFEM().assembleVector(*q_e, *residual, dof_synchronizer->getLocalDOFEquationNumbers(), 1, *it,ghost_type,NULL,-1); delete q_e; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::solveExplicitLumped() { AKANTU_DEBUG_IN(); UInt nb_nodes = increment->getSize(); UInt nb_degre_of_freedom = increment->getNbComponent(); Real * capa_val = capacity_lumped->values; Real * res_val = residual->values; bool * boundary_val = boundary->values; Real * inc = increment->values; for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n) { if(!(*boundary_val)) { *inc = (*res_val / *capa_val); } res_val++; boundary_val++; inc++; capa_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitPred() { AKANTU_DEBUG_IN(); integrator->integrationSchemePred(time_step, *temperature, *temperature_rate, *boundary); UInt nb_nodes = temperature->getSize(); UInt nb_degre_of_freedom = temperature->getNbComponent(); Real * temp = temperature->values; for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n, ++temp) if(*temp < 0.) *temp = 0.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrTempRate(time_step, *temperature, *temperature_rate, *boundary, *increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real HeatTransferModel::getStableTimeStep() { AKANTU_DEBUG_IN(); Real conductivitymax = -std::numeric_limits::max(); Real el_size; Real min_el_size = std::numeric_limits::max(); Real * coord = getFEM().getMesh().getNodes().values; const Mesh::ConnectivityTypeList & type_list = getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_nodes_per_element = getFEM().getMesh().getNbNodesPerElement(*it); UInt nb_element = getFEM().getMesh().getNbElement(*it); - UInt * conn = getFEM().getMesh().getConnectivity(*it).values; + UInt * conn = getFEM().getMesh().getConnectivity(*it, _not_ghost).values; Real * u = new Real[nb_nodes_per_element*spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(u + n * spatial_dimension, coord + offset_conn, spatial_dimension * sizeof(Real)); } el_size = getFEM().getElementInradius(u, *it); //get the biggest parameter from k11 until k33// for(UInt i = 0; i < spatial_dimension * spatial_dimension; i++) { if(conductivity[i] > conductivitymax) conductivitymax=conductivity[i]; } min_el_size = std::min(min_el_size, el_size); } AKANTU_DEBUG_INFO("The minimum element size : " << min_el_size << " and the max conductivity is : " << conductivitymax); delete [] u; } Real min_dt = 2 * min_el_size * min_el_size * density * capacity/conductivitymax; StaticCommunicator::getStaticCommunicator()->allReduce(&min_dt, 1, _so_min); AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ void HeatTransferModel::readMaterials(const std::string & filename) { Parser parser; parser.open(filename); std::string mat_type = parser.getNextSection("heat"); if (mat_type != ""){ parser.readSection(*this); } else AKANTU_DEBUG_ERROR("did not find any section with material info " <<"for heat conduction"); } /* -------------------------------------------------------------------------- */ void HeatTransferModel::setParam(const std::string & key, const std::string & value) { std::stringstream str(value); if (key == "conductivity") { conductivity = new Real[spatial_dimension * spatial_dimension]; for(UInt i = 0; i < 3; i++) for(UInt j = 0; j < 3; j++) { if (i< spatial_dimension && j < spatial_dimension){ str >> conductivity[i*spatial_dimension+j]; AKANTU_DEBUG_INFO("Conductivity(" << i << "," << j << ") = " << conductivity[i*spatial_dimension+j]); } else { Real tmp; str >> tmp; } } } else if (key == "capacity"){ str >> capacity; AKANTU_DEBUG_INFO("The capacity of the material is:" << capacity); } else if (key == "density"){ str >> density; AKANTU_DEBUG_INFO("The density of the material is:" << density); } } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/heat_transfer/heat_transfer_model.hh b/model/heat_transfer/heat_transfer_model.hh index 48f9fa44b..42de233d1 100644 --- a/model/heat_transfer/heat_transfer_model.hh +++ b/model/heat_transfer/heat_transfer_model.hh @@ -1,265 +1,257 @@ /** * @file heat_transfer_model.hh * @author Rui WANG * @date Fri May 4 13:35:55 2011 * * @brief Model of Heat Transfer * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_HEAT_TRANSFER_MODEL_HH__ #define __AKANTU_HEAT_TRANSFER_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "model.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" namespace akantu { class IntegrationScheme1stOrder; // class Solver; // class SparseMatrix; } __BEGIN_AKANTU__ class HeatTransferModel : public Model, public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEMTemplate MyFEMType; HeatTransferModel(UInt spatial_dimension, const ModelID & id = "heat_transfer_model", const MemoryID & memory_id = 0) ; HeatTransferModel(Mesh & mesh, UInt spatial_dimension = 0, const ModelID & id = "heat_transfer_model", const MemoryID & memory_id = 0); virtual ~HeatTransferModel() ; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// set the parameters void setParam(const std::string & key, const std::string & value); /// read one material file to instantiate all the materials void readMaterials(const std::string & filename); /// allocate all vectors void initVectors(); /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL); /// initialize the model void initModel(); /// init PBC synchronizer void initPBC(UInt x,UInt y, UInt z); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const {}; /* ------------------------------------------------------------------------ */ /* Methods for explicit */ /* ------------------------------------------------------------------------ */ public: /// compute and get the stable time step Real getStableTimeStep(); /// compute the heat flux void updateResidual(); /// solve the system in temperature rate @f$C\delta \dot T = q_{n+1} - C \dot T_{n}@f$ void solveExplicitLumped(); /// calculate the lumped capacity vector for heat transfer problem void assembleCapacityLumped(); /// update the temperature from the temperature rate void explicitPred(); /// update the temperature rate from the increment void explicitCorr(); // /// initialize the heat flux // void initializeResidual(Vector &temp); // /// initialize temperature // void initializeTemperature(Vector &temp); private: /// compute the heat flux on ghost types void updateResidual(const GhostType & ghost_type); /// calculate the lumped capacity vector for heat transfer problem (w ghosttype) void assembleCapacityLumped(const GhostType & ghost_type); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline UInt getNbDataToPack(const Element & element, SynchronizationTag tag) const; inline UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const; inline void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline UInt getNbDataToPack(SynchronizationTag tag) const; inline UInt getNbDataToUnpack(SynchronizationTag tag) const; inline void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the current value of the time step AKANTU_GET_MACRO(TimeStep, time_step, Real); /// set the value of the time step AKANTU_SET_MACRO(TimeStep, time_step, Real); /// get the assembled heat flux AKANTU_GET_MACRO(Residual, *residual, Vector&); /// get the lumped capacity AKANTU_GET_MACRO(CapacityLumped, * capacity_lumped, Vector&); /// get the boundary vector AKANTU_GET_MACRO(Boundary, * boundary, Vector&); /// get the temperature gradient - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(TemperatureGradient, temperature_gradient, Vector &); - /// get the temperature gradient for ghosts - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(TemperatureGradientGhost, temperature_gradient_ghost, Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(TemperatureGradient, temperature_gradient, Real); /// get the temperature AKANTU_GET_MACRO(Temperature, *temperature, Vector &); /// get the temperature derivative AKANTU_GET_MACRO(TemperatureRate, *temperature_rate, Vector &); /// get the equation number Vector AKANTU_GET_MACRO(EquationNumber, *equation_number, const Vector &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: IntegrationScheme1stOrder * integrator; /// time step Real time_step; /// temperatures array Vector * temperature; /// temperatures derivatives array Vector * temperature_rate; /// increment array (@f$\delta \dot T@f$ or @f$\delta T@f$) Vector * increment; /// the spatial dimension UInt spatial_dimension; /// the density Real density; /// the speed of the changing temperature ByElementTypeReal temperature_gradient; - /// the speed of the changing temperature ghost version - ByElementTypeReal temperature_gradient_ghost; - - /// K*T internal flux vector - Vector * heat_flux; - //external flux vector + Vector * external_flux; - Vector * externalFlux; /// residuals array Vector * residual; /// position of a dof in the K matrix Vector * equation_number; //lumped vector Vector * capacity_lumped; /// boundary vector Vector * boundary; //realtime Real time; ///capacity Real capacity; //conductivity matrix Real* conductivity; //the biggest parameter of conductivity matrix Real conductivitymax; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "heat_transfer_model_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const HeatTransferModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_HEAT_TRANSFER_MODEL_HH__ */ diff --git a/model/heat_transfer/heat_transfer_model_inline_impl.cc b/model/heat_transfer/heat_transfer_model_inline_impl.cc index 3f6738fd6..409ba734c 100644 --- a/model/heat_transfer/heat_transfer_model_inline_impl.cc +++ b/model/heat_transfer/heat_transfer_model_inline_impl.cc @@ -1,359 +1,359 @@ /** * @file heat_transfer_model_inline_impl.cc * @author Srinivasa Babu Ramisetti * @date Fri Mar 4 17:04:25 2011 * * @brief Implementation of the inline functions of the HeatTransferModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ inline UInt HeatTransferModel::getNbDataToPack(SynchronizationTag tag) const{ AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes = getFEM().getMesh().getNbNodes(); switch(tag) { case _gst_htm_temperature: case _gst_htm_capacity: { size += nb_nodes * sizeof(Real); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; }; /* -------------------------------------------------------------------------- */ inline UInt HeatTransferModel::getNbDataToUnpack(SynchronizationTag tag) const{ AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes = getFEM().getMesh().getNbNodes(); switch(tag) { case _gst_htm_capacity: case _gst_htm_temperature: { size += nb_nodes * sizeof(Real); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; }; /* -------------------------------------------------------------------------- */ inline void HeatTransferModel::packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const{ AKANTU_DEBUG_IN(); switch(tag) { case _gst_htm_capacity: buffer << (*capacity_lumped)(index); break; case _gst_htm_temperature: { buffer << (*temperature)(index); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); }; /* -------------------------------------------------------------------------- */ inline void HeatTransferModel::unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const{ AKANTU_DEBUG_IN(); switch(tag) { case _gst_htm_capacity: { buffer >> (*capacity_lumped)(index); break; } case _gst_htm_temperature: { buffer >> (*temperature)(index); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); }; /* -------------------------------------------------------------------------- */ inline UInt HeatTransferModel::getNbDataToPack(const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifndef AKANTU_NDEBUG size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check) size += spatial_dimension * nb_nodes_per_element * sizeof(Real); /// position of the nodes of the element #endif switch(tag) { case _gst_htm_capacity: { size += nb_nodes_per_element * sizeof(Real); // capacity vector break; } case _gst_htm_temperature: { size += nb_nodes_per_element * sizeof(Real); // temperature break; } case _gst_htm_gradient_temperature: { size += spatial_dimension * sizeof(Real); // temperature gradient size += nb_nodes_per_element * sizeof(Real); // nodal temperatures size += spatial_dimension * nb_nodes_per_element * sizeof(Real); // shape derivatives break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline UInt HeatTransferModel::getNbDataToUnpack(const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifndef AKANTU_NDEBUG size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check) size += spatial_dimension * nb_nodes_per_element * sizeof(Real); /// position of the nodes of the element #endif switch(tag) { case _gst_htm_capacity: { size += nb_nodes_per_element * sizeof(Real); // capacity vector break; } case _gst_htm_temperature: { size += nb_nodes_per_element * sizeof(Real); // temperature break; } case _gst_htm_gradient_temperature: { size += spatial_dimension * sizeof(Real); // temperature gradient size += nb_nodes_per_element * sizeof(Real); // nodal temperatures size += spatial_dimension * nb_nodes_per_element * sizeof(Real); // shape derivatives break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void HeatTransferModel::packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const { - + GhostType ghost_type = _not_ghost; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; - UInt * conn = getFEM().getMesh().getConnectivity(element.type).values; + UInt * conn = getFEM().getMesh().getConnectivity(element.type, ghost_type).values; #ifndef AKANTU_NDEBUG types::RVector barycenter(spatial_dimension); - getFEM().getMesh().getBarycenter(element.element, element.type, barycenter.storage()); + getFEM().getMesh().getBarycenter(element.element, element.type, barycenter.storage(), ghost_type); buffer << barycenter; Real * nodes = getFEM().getMesh().getNodes().values; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; for (UInt s = 0; s < spatial_dimension; ++s) { buffer << nodes[spatial_dimension*offset_conn+s]; } } #endif switch (tag){ case _gst_htm_capacity: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer << (*capacity_lumped)(offset_conn); } break; } case _gst_htm_temperature: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer << (*temperature)(offset_conn); } break; } case _gst_htm_gradient_temperature: { Vector::iterator it_gtemp = - temperature_gradient[element.type]->begin(spatial_dimension); + temperature_gradient(element.type, ghost_type)->begin(spatial_dimension); buffer << it_gtemp[element.element]; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer << (*temperature)(offset_conn); } Vector::iterator it_shaped = - const_cast &>(getFEM().getShapesDerivatives(element.type)) + const_cast &>(getFEM().getShapesDerivatives(element.type, ghost_type)) .begin(nb_nodes_per_element,spatial_dimension); buffer << it_shaped[element.element]; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } } /* -------------------------------------------------------------------------- */ inline void HeatTransferModel::unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const { - + GhostType ghost_type = _ghost; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; - UInt * conn = getFEM().getMesh().getConnectivity(element.type,_ghost).values; + UInt * conn = getFEM().getMesh().getConnectivity(element.type, ghost_type).values; #ifndef AKANTU_NDEBUG types::RVector barycenter_loc(spatial_dimension); - getFEM().getMesh().getBarycenter(element.element, element.type, barycenter_loc.storage(), _ghost); + getFEM().getMesh().getBarycenter(element.element, element.type, barycenter_loc.storage(), ghost_type); types::RVector barycenter(spatial_dimension); buffer >> barycenter; Real tolerance = 1e-15; for (UInt i = 0; i < spatial_dimension; ++i) { if(!(std::abs(barycenter(i) - barycenter_loc(i)) <= tolerance)) AKANTU_EXCEPTION("Unpacking an unknown value for the element : " << element << "(barycenter[" << i << "] = " << barycenter_loc(i) << " and buffer[" << i << "] = " << barycenter(i) << ")"); } types::RVector coords(spatial_dimension); Real * nodes = getFEM().getMesh().getNodes().values; for (UInt n = 0; n < nb_nodes_per_element; ++n) { buffer >> coords; UInt offset_conn = conn[el_offset + n]; Real tolerance = 1e-15; Real * coords_local = nodes+spatial_dimension*offset_conn; for (UInt i = 0; i < spatial_dimension; ++i) { if(!(std::abs(coords(i) - coords_local[i]) <= tolerance)) AKANTU_EXCEPTION("Unpacking to wrong node for the element : " << element << "(coords[" << i << "] = " << coords_local[i] << " and buffer[" << i << "] = " << coords(i) << ")"); } } #endif switch (tag){ case _gst_htm_capacity: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer >> (*capacity_lumped)(offset_conn); } break; } case _gst_htm_temperature: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; Real tbuffer; buffer >> tbuffer; #ifndef AKANTU_NDEBUG // if (!getFEM().getMesh().isPureGhostNode(offset_conn)){ // if (std::abs(tbuffer - (*temperature)(offset_conn)) > 1e-15){ // AKANTU_EXCEPTION(std::scientific << std::setprecision(20) // << "local node is impacted with a different value computed from a distant proc" // << " => divergence of trajectory detected " << std::endl // << tbuffer << " != " << (*temperature)(offset_conn) // << " diff is " << tbuffer - (*temperature)(offset_conn)); // } // } #endif (*temperature)(offset_conn) = tbuffer; } break; } case _gst_htm_gradient_temperature: { Vector::iterator it_gtemp = - temperature_gradient_ghost[element.type]->begin(spatial_dimension); + temperature_gradient(element.type, ghost_type)->begin(spatial_dimension); types::RVector gtemp(spatial_dimension); types::RVector temp_nodes(nb_nodes_per_element); types::Matrix shaped(nb_nodes_per_element,spatial_dimension); buffer >> gtemp; buffer >> temp_nodes; buffer >> shaped; // Real tolerance = 1e-15; if (!Math::are_vector_equal(spatial_dimension,gtemp.storage(),it_gtemp[element.element].storage())){ Real dist = Math::distance_3d(gtemp.storage(), it_gtemp[element.element].storage()); debug::_akantu_debug_cout->precision(20); std::stringstream temperatures_str; temperatures_str.precision(20); temperatures_str << std::scientific << "temperatures are "; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; temperatures_str << (*temperature)(offset_conn) << " "; } Vector::iterator it_shaped = - const_cast &>(getFEM().getShapesDerivatives(element.type,_ghost)) + const_cast &>(getFEM().getShapesDerivatives(element.type, ghost_type)) .begin(nb_nodes_per_element,spatial_dimension); AKANTU_EXCEPTION("packed gradient do not match for element " << element.element << std::endl << "buffer is " << gtemp << " local is " << it_gtemp[element.element] << " dist is " << dist << std::endl << temperatures_str.str() << std::endl << std::scientific << std::setprecision(20) << " distant temperatures " << temp_nodes - << "temperature gradient size " << temperature_gradient_ghost[element.type]->getSize() + << "temperature gradient size " << temperature_gradient(element.type, ghost_type)->getSize() << " number of ghost elements " << getFEM().getMesh().getNbElement(element.type,_ghost) << std::scientific << std::setprecision(20) << " shaped " << shaped << std::scientific << std::setprecision(20) << " local shaped " << it_shaped[element.element]); } break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } } /* -------------------------------------------------------------------------- */ diff --git a/model/solid_mechanics/contact.cc b/model/solid_mechanics/contact.cc index eff8e7051..859cba1fc 100644 --- a/model/solid_mechanics/contact.cc +++ b/model/solid_mechanics/contact.cc @@ -1,266 +1,262 @@ /** * @file contact.cc * @author David Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @date Fri Oct 8 14:55:42 2010 * * @brief Common part of contact classes * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact.hh" #include "contact_search.hh" #include "aka_common.hh" #include "contact_3d_explicit.hh" #include "contact_search_explicit.hh" #include "contact_2d_explicit.hh" #include "contact_search_2d_explicit.hh" #include "contact_rigid.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Contact::Contact(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), model(model), type(type) { AKANTU_DEBUG_IN(); - for (UInt i = 0; i < _max_element_type; ++i) { - node_to_elements_offset[i] = NULL; - node_to_elements[i] = NULL; - } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact::~Contact() { AKANTU_DEBUG_IN(); delete contact_search; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initContact(bool add_surfaces_flag) { AKANTU_DEBUG_IN(); Mesh & mesh = model.getFEM().getMesh(); /// Build surfaces if not done yet if(mesh.getNbSurfaces() == 0) { /* initialise nb_surfaces to zero in mesh_io */ MeshUtils::buildFacets(mesh,1,0); MeshUtils::buildSurfaceID(mesh); } /// Detect facet types const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; UInt spatial_dimension = mesh.getSpatialDimension(); for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) != spatial_dimension) continue; facet_type[nb_facet_types] = mesh.getFacetElementType(type); nb_facet_types++; } CSR suface_nodes; MeshUtils::buildNodesPerSurface(mesh, suface_nodes); suface_nodes.copy(surface_to_nodes_offset, surface_to_nodes); for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; std::stringstream sstr_name_1; sstr_name_1 << id << ":node_to_elements_offset:" << type; - this->node_to_elements_offset[type] = &(alloc(sstr_name_1.str(),0,1)); + this->node_to_elements_offset(type, _not_ghost) = &(alloc(sstr_name_1.str(),0,1)); std::stringstream sstr_name_2; sstr_name_2 << id << ":node_to_elements:" << type; - this->node_to_elements[type] = &(alloc(sstr_name_2.str(),0,1)); + this->node_to_elements(type, _not_ghost) = &(alloc(sstr_name_2.str(),0,1)); CSR node_to_elem; MeshUtils::buildNode2ElementsByElementType(mesh, type, node_to_elem); - node_to_elem.copy(*node_to_elements_offset[type], *node_to_elements[type]); + node_to_elem.copy(*node_to_elements_offset(type, _not_ghost), *node_to_elements(type, _not_ghost)); } if(add_surfaces_flag) { for (UInt i = 0; i < mesh.getNbSurfaces(); ++i) { addMasterSurface(i); std::cout << "Master surface " << i << " has been added automatically" << std::endl; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initSearch() { AKANTU_DEBUG_IN(); contact_search->initSearch(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initNeighborStructure() { AKANTU_DEBUG_IN(); contact_search->initNeighborStructure(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::initNeighborStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); contact_search->initNeighborStructure(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::checkAndUpdate() { AKANTU_DEBUG_IN(); std::vector::iterator it; for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { if(contact_search->checkIfUpdateStructureNeeded(*it)) { contact_search->updateStructure(*it); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::updateContact() { AKANTU_DEBUG_IN(); std::vector::iterator it; for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { contact_search->updateStructure(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::addMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(std::find(master_surfaces.begin(), master_surfaces.end(), master_surface) == master_surfaces.end(), "Master surface already registered in the master surface list"); master_surfaces.push_back(master_surface); contact_search->addMasterSurface(master_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact::removeMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(std::find(master_surfaces.begin(), master_surfaces.end(), master_surface) != master_surfaces.end(), "Master surface not registered in the master surface list"); std::remove(master_surfaces.begin(), master_surfaces.end(), master_surface); contact_search->removeMasterSurface(master_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact * Contact::newContact(const SolidMechanicsModel & model, const ContactType & contact_type, const ContactSearchType & contact_search_type, const ContactNeighborStructureType & contact_neighbor_structure_type, const ContactID & id, const MemoryID & memory_id) { AKANTU_DEBUG_IN(); Contact * tmp_contact = NULL; ContactSearch * tmp_search = NULL; switch(contact_type) { case _ct_2d_expli: { tmp_contact = new Contact2dExplicit(model, contact_type, id, memory_id); break; } case _ct_3d_expli: { tmp_contact = new Contact3dExplicit(model, contact_type, id, memory_id); break; } case _ct_rigid: { tmp_contact = new ContactRigid(model, contact_type, id, memory_id); break; } case _ct_not_defined: { AKANTU_DEBUG_ERROR("Not a valid contact type : " << contact_type); break; } } std::stringstream sstr; sstr << id << ":contact_search"; switch(contact_search_type) { case _cst_2d_expli: { tmp_search = new ContactSearch2dExplicit(*tmp_contact, contact_neighbor_structure_type, contact_search_type, sstr.str()); break; } case _cst_expli: { tmp_search = new ContactSearchExplicit(*tmp_contact, contact_neighbor_structure_type, contact_search_type, sstr.str()); break; } case _cst_not_defined: { AKANTU_DEBUG_ERROR("Not a valid contact search type : " << contact_search_type); break; } } AKANTU_DEBUG_OUT(); return tmp_contact; } __END_AKANTU__ diff --git a/model/solid_mechanics/contact.hh b/model/solid_mechanics/contact.hh index 4c345b4f0..dad316567 100644 --- a/model/solid_mechanics/contact.hh +++ b/model/solid_mechanics/contact.hh @@ -1,177 +1,177 @@ /** * @file contact.hh * @author Nicolas Richart * @author David Kammer * @author Leonardo Snozzi * @date Mon Sep 27 09:47:27 2010 * * @brief Interface for contact classes * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_HH__ #define __AKANTU_CONTACT_HH__ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" //#include "contact_search.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ContactSearch; class PenetrationList; } __BEGIN_AKANTU__ class Contact : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ protected: Contact(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id = "contact", const MemoryID & memory_id = 0); public: virtual ~Contact(); static Contact * newContact(const SolidMechanicsModel & model, const ContactType & contact_type, const ContactSearchType & contact_search_type, const ContactNeighborStructureType & contact_neighbor_structure_type, const ContactID & id = "contact", const MemoryID & memory_id = 0); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// update the internal structures virtual void initContact(bool add_surfaces_flag = true); /// initiate the contact search structure virtual void initSearch(); /// initialize all neighbor structures virtual void initNeighborStructure(); /// initialize one neighbor structure virtual void initNeighborStructure(const Surface & master_surface); /// check if the neighbor structure need an update virtual void checkAndUpdate(); /// update the internal structures virtual void updateContact(); /// solve the contact virtual void solveContact() = 0; /// add a new master surface virtual void addMasterSurface(const Surface & master_surface); /// remove a master surface virtual void removeMasterSurface(const Surface & master_surface); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const ContactID &); AKANTU_GET_MACRO(Model, model, const SolidMechanicsModel &); AKANTU_GET_MACRO(ContactSearch, * contact_search, const ContactSearch &); AKANTU_GET_MACRO(SurfaceToNodesOffset, surface_to_nodes_offset, const Vector &); AKANTU_GET_MACRO(SurfaceToNodes, surface_to_nodes, const Vector &); AKANTU_GET_MACRO(MasterSurfaces, master_surfaces, const std::vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NodeToElementsOffset, node_to_elements_offset, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NodeToElementsOffset, node_to_elements_offset, UInt); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(NodeToElements, node_to_elements, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(NodeToElements, node_to_elements, UInt); AKANTU_GET_MACRO(Type, type, const ContactType &); void setContactSearch(ContactSearch & contact_search) { this->contact_search = &contact_search; } /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the contact class ContactID id; /// associated model const SolidMechanicsModel & model; /// contact search object ContactSearch * contact_search; /// list of master surfaces std::vector master_surfaces; /// type of contact object ContactType type; private: /// offset of nodes per surface Vector surface_to_nodes_offset; /// list of surface nodes @warning Node can occur multiple time Vector surface_to_nodes; /// offset of surface elements per surface node ByElementTypeUInt node_to_elements_offset; /// list of surface elements id (elements can occur multiple times) ByElementTypeUInt node_to_elements; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "contact_inline_impl.cc" /// standard output stream operator // inline std::ostream & operator <<(std::ostream & stream, const Contact & _this) // { // _this.printself(stream); // return stream; //} __END_AKANTU__ #endif /* __AKANTU_CONTACT_HH__ */ diff --git a/model/solid_mechanics/contact/contact_2d_explicit.cc b/model/solid_mechanics/contact/contact_2d_explicit.cc index 814960735..1b0b4777a 100755 --- a/model/solid_mechanics/contact/contact_2d_explicit.cc +++ b/model/solid_mechanics/contact/contact_2d_explicit.cc @@ -1,386 +1,405 @@ /** * @file contact_2d_explicit.cc * @author Leonardo Snozzi * @date Tue Oct 5 16:23:56 2010 * * @brief Contact class for explicit contact in 2d based on DCR algorithm * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_2d_explicit.hh" #include "contact_search.hh" #include "aka_vector.hh" #define PROJ_TOL 1.E-8 __BEGIN_AKANTU__ Contact2dExplicit::Contact2dExplicit(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : - Contact(model, type, id, memory_id), friction_coefficient(0.), + Contact(model, type, id, memory_id), friction_coefficient(0.), coefficient_of_restitution(0.) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model.getFEM().getMesh().getSpatialDimension(); if(spatial_dimension != 2) AKANTU_DEBUG_ERROR("Wrong ContactType for contact in 2d!"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Contact2dExplicit::~Contact2dExplicit() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } // void Contact2dExplicit::defineSurfaces() { // AKANTU_DEBUG_IN(); // Mesh & mesh = model.fem->getMesh(); // // const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // // UInt nb_types = type_list.size(); // /// Declare vectors // // Vector node_offset; // // Vector node_to_elem // ; // UInt * facet_conn_val = NULL; // UInt nb_facet_elements; // /// Consider only linear facet elements // // for(it = type_list.begin(); it != type_list.end(); ++it) { // ElementType facet_type; // // if(type == _line_1) { // nb_facet_elements = mesh.getNbElement(facet_type); // facet_conn_val = mesh.getConnectivity(facet_type).values; // // buildNode2ElementsByElementType(mesh, facet_type, node_offset, node_to_elem); - + // /// Ricominciamo usando le funzioni di più alto livello in mesh // const UInt nb_surfaces = getNbSurfaces(facet_type); // nb_facet_elements = mesh.getNbElement(facet_type); // const Vector * elem_to_surf_val = getSurfaceValues(facet_type).values; - + // for (UInt i = 0; i < nb_surfaces; ++i) // addMasterSurface(i); - + // /// OK ora riordinare le superfici con i rispettivi nodi ed elementi (in linea) // surf_to_node_offset.resize(nb_surfaces+1); // for (UInt i = 0; i < nb_facet_elements; ++i) // surf_to_elem_offset.val[elem_to_surf_val[i]]++; // /// rearrange surf_to_elem_offset // for (UInt i = 1; i < nb_surfaces; ++i) surf_to_elem_offset.values[i] += surf_to_elem_offset.values[i-1]; // for (UInt i = nb_surfaces; i > 0; --i) surf_to_elem_offset.values[i] = surf_to_elem_offset[i-1]; // surf_to_elem_offset.values[0] = 0; - + // for (UInt i = 0; i < nb_facet_elements; ++i) // surf_to_elem[elem_to_surf_val[]] // AKANTU_DEBUG_OUT(); // } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::solveContact() { AKANTU_DEBUG_IN(); /// Loop over master surfaces std::vector::iterator it; std::vector master_surfaces = getMasterSurfaces(); for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { - + /// Get penetration list (find node to segment penetration) - + PenetrationList pen_list; contact_search->findPenetration(*it, pen_list); if(pen_list.penetrating_nodes.getSize() > 0) { Vector vel_norm(0, 2); Vector vel_fric(0, 2); Vector nodes_index(0, 2); /// Remove node to segment penetrations projectNodesOnSegments(pen_list, nodes_index); /// Compute normal velocities of impacting nodes according to the normal linear momenta computeNormalVelocities(pen_list, nodes_index, vel_norm); /// Compute friction velocities computeFrictionVelocities(pen_list, nodes_index, vel_norm, vel_fric); /// Update post-impact velocities updatePostImpactVelocities(pen_list, nodes_index, vel_norm, vel_fric); } - } + } + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::projectNodesOnSegments(PenetrationList & pen_list, Vector & nodes_index) { AKANTU_DEBUG_IN(); - + UInt dim = 2; + ElementType el_type = _segment_2; + const SolidMechanicsModel & model = getModel(); Real * inc_val = model.getIncrement().values; Real * disp_val = model.getDisplacement().values; Real * pos_val = model.getCurrentPosition().values; - Real * delta = new Real[dim*pen_list.penetrating_nodes.getSize()]; - ElementType el_type = _segment_2; - UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; + Vector & pen_nodes = pen_list.penetrating_nodes; + Vector & pen_facets_off = *pen_list.penetrated_facets_offset(el_type, _not_ghost); + Vector & pen_facets = *pen_list.penetrated_facets(el_type, _not_ghost); + Vector & projected_positions = *pen_list.projected_positions(el_type, _not_ghost); + Vector & gaps = *pen_list.gaps(el_type, _not_ghost); + Vector & facets_normals = *pen_list.facets_normals(el_type, _not_ghost); + + Real * delta = new Real[dim*pen_nodes.getSize()]; + + UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type, _not_ghost).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); - nodes_index.resize(3*pen_list.penetrating_nodes.getSize()); + + nodes_index.resize(3*pen_nodes.getSize()); + UInt * index = nodes_index.values; - for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { - const UInt i_node = pen_list.penetrating_nodes.values[n]; - for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { + for (UInt n = 0; n < pen_nodes.getSize(); ++n) { + const UInt i_node = pen_nodes(n); + for (UInt el = pen_facets_off(n); el < pen_facets_off(n+1); ++el) { /// Project node on segment according to its projection - Real proj = pen_list.projected_positions[el_type]->values[n]; + Real proj = projected_positions(n); - index[n*3] = conn_val[elem_nodes*pen_list.penetrated_facets[el_type]->values[n]]; - index[n*3+1] = conn_val[elem_nodes*pen_list.penetrated_facets[el_type]->values[n]+1]; + index[n*3] = conn_val[elem_nodes*pen_facets(n)]; + index[n*3+1] = conn_val[elem_nodes*pen_facets(n) + 1]; index[n*3+2] = i_node; if(proj > PROJ_TOL && proj < 1.-PROJ_TOL) { - delta[2*n] = -pen_list.gaps[el_type]->values[n]*pen_list.facets_normals[el_type]->values[dim*el]; - delta[2*n+1] = -pen_list.gaps[el_type]->values[n]*pen_list.facets_normals[el_type]->values[dim*el+1]; + delta[2*n] = -gaps(n)*facets_normals(el, 0); + delta[2*n+1] = -gaps(n)*facets_normals(el, 1); } else if(proj <= PROJ_TOL) { - delta[2*n] = pos_val[dim*index[n*3]]-pos_val[dim*i_node]; - delta[2*n+1] = pos_val[dim*index[n*3]+1]-pos_val[dim*i_node+1]; + delta[2*n] = pos_val[dim*index[n*3]] - pos_val[dim*i_node]; + delta[2*n+1] = pos_val[dim*index[n*3]+1] - pos_val[dim*i_node+1]; if(proj < -PROJ_TOL) { Real modulus = sqrt(delta[2*n]*delta[2*n]+delta[2*n+1]*delta[2*n+1]); - pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n]/modulus; - pen_list.facets_normals[el_type]->values[dim*el+1] = delta[2*n+1]/modulus; + facets_normals(el, 0) = delta[2*n]/modulus; + facets_normals(el, 1) = delta[2*n+1]/modulus; } proj = 0.; } else { /* proj >= 1.- PROJ_TOL */ - delta[2*n] = pos_val[dim*index[n*3+1]]-pos_val[dim*i_node]; - delta[2*n+1] = pos_val[dim*index[n*3+1]+1]-pos_val[dim*i_node+1]; + delta[2*n] = pos_val[dim*index[n*3+1]] - pos_val[dim*i_node]; + delta[2*n+1] = pos_val[dim*index[n*3+1]+1] - pos_val[dim*i_node+1]; if(proj > 1.+PROJ_TOL) { Real modulus = sqrt(delta[2*n]*delta[2*n]+delta[2*n+1]*delta[2*n+1]); - pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n]/modulus; - pen_list.facets_normals[el_type]->values[dim*el] = delta[2*n+1]/modulus; + facets_normals(el, 0) = delta[2*n]/modulus; + facets_normals(el, 0) = delta[2*n+1]/modulus; + // Note from Nicolas : I put the same index during the modification, + // but shouldn't it be facets_normals(el, 0) on the second line ? } proj = 1.; } } } /// Update displacement and increment of the projected nodes - for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { - UInt i_node = pen_list.penetrating_nodes.values[n]; - - pos_val[dim*index[n*3+2]] +=delta[2*n]; - pos_val[dim*index[n*3+2]+1] += delta[2*n+1]; - disp_val[dim*index[n*3+2]] += delta[2*n]; + for (UInt n = 0; n < pen_nodes.getSize(); ++n) { + UInt i_node = pen_nodes.values[n]; + + pos_val[dim*index[n*3+2]] += delta[2*n]; + pos_val[dim*index[n*3+2]+1] += delta[2*n+1]; + disp_val[dim*index[n*3+2]] += delta[2*n]; disp_val[dim*index[n*3+2]+1] += delta[2*n+1]; - inc_val[dim*index[n*3+2]] += delta[2*n]; - inc_val[dim*index[n*3+2]+1] +=delta[2*n+1]; + inc_val[dim*index[n*3+2]] += delta[2*n]; + inc_val[dim*index[n*3+2]+1] += delta[2*n+1]; } delete [] delta; AKANTU_DEBUG_OUT(); } -void Contact2dExplicit::computeNormalVelocities(PenetrationList & pen_list, - Vector & nodes_index, +void Contact2dExplicit::computeNormalVelocities(PenetrationList & pen_list, + Vector & nodes_index, Vector & vel_norm) { AKANTU_DEBUG_IN(); const UInt dim = 2; const SolidMechanicsModel & model = getModel(); const ElementType el_type = _segment_2; - UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; + UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type, _not_ghost).values; const UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); - + + Vector & projected_positions = *pen_list.projected_positions(el_type, _not_ghost); + Vector & facets_normals = *pen_list.facets_normals(el_type, _not_ghost); + Real * vel_val = model.getVelocity().values; Real * mass_val = model.getMass().values; Real * pos_val = model.getCurrentPosition().values; vel_norm.resize(6*pen_list.penetrating_nodes.getSize()); Real * v_n = vel_norm.values; UInt * index = nodes_index.values; Real dg[6]; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { - + // for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { - Real proj = pen_list.projected_positions[el_type]->values[n]; + Real proj = projected_positions(n); /// Fill gap derivative if (proj < PROJ_TOL) { - dg[0] = pen_list.facets_normals[el_type]->values[2*n+0]; - dg[1] = pen_list.facets_normals[el_type]->values[2*n+1]; + dg[0] = facets_normals(n, 0); + dg[1] = facets_normals(n, 1); dg[2] = 0.; dg[3] = 0.; - dg[4] = -pen_list.facets_normals[el_type]->values[2*n+0]; - dg[5] = -pen_list.facets_normals[el_type]->values[2*n+1]; + dg[4] = -facets_normals(n, 0); + dg[5] = -facets_normals(n, 1); } else if (proj > 1.-PROJ_TOL) { dg[0] = 0.; dg[1] = 0.; - dg[2] = pen_list.facets_normals[el_type]->values[2*n+0]; - dg[3] = pen_list.facets_normals[el_type]->values[2*n+1]; - dg[4] = -pen_list.facets_normals[el_type]->values[2*n+0]; - dg[5] = -pen_list.facets_normals[el_type]->values[2*n+1]; + dg[2] = facets_normals(n, 0); + dg[3] = facets_normals(n, 1); + dg[4] = -facets_normals(n, 0); + dg[5] = -facets_normals(n, 1); } else { - dg[0] = pos_val[index[n*3+2]*dim+1]-pos_val[index[n*3+1]*dim+1]; - dg[1] = pos_val[index[n*3+1]*dim]-pos_val[index[n*3+2]*dim]; - dg[2] = pos_val[index[n*3]*dim+1]-pos_val[index[n*3+2]*dim+1]; - dg[3] = pos_val[index[n*3+2]*dim]-pos_val[index[n*3]*dim]; - dg[4] = pos_val[index[n*3+1]*dim+1]-pos_val[index[n*3]*dim+1]; - dg[5] = pos_val[index[n*3]*dim]-pos_val[index[n*3+1]*dim]; + dg[0] = pos_val[index[n*3+2]*dim+1] - pos_val[index[n*3+1]*dim+1]; + dg[1] = pos_val[index[n*3+1]*dim] - pos_val[index[n*3+2]*dim]; + dg[2] = pos_val[index[n*3]*dim+1] - pos_val[index[n*3+2]*dim+1]; + dg[3] = pos_val[index[n*3+2]*dim] - pos_val[index[n*3]*dim]; + dg[4] = pos_val[index[n*3+1]*dim+1] - pos_val[index[n*3]*dim+1]; + dg[5] = pos_val[index[n*3]*dim] - pos_val[index[n*3+1]*dim]; } /// Compute normal velocities exchanged during impact Real temp1 = 0., temp2 = 0.; for (UInt i=0; i<3; ++i) for (UInt j = 0; j < dim; ++j) { temp1 += dg[i*dim+j]*vel_val[dim*index[3*n+i]+j]; temp2 += dg[i*dim+j]*dg[i*dim+j]/mass_val[index[3*n+i]]; } temp1 /= temp2; for (UInt i=0; i<3; ++i) for (UInt j = 0; j < dim; ++j) v_n[n*6+i*dim+j] = temp1*dg[i*dim+j]/mass_val[index[3*n+i]]; // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ - void Contact2dExplicit::computeFrictionVelocities(PenetrationList & pen_list, - Vector & nodes_index, + void Contact2dExplicit::computeFrictionVelocities(PenetrationList & pen_list, + Vector & nodes_index, Vector & vel_norm, Vector & vel_fric) { AKANTU_DEBUG_IN(); vel_fric.resize(6*pen_list.penetrating_nodes.getSize()); if (getFrictionCoefficient() == 0) { memset(vel_fric.values, 0, (6*pen_list.penetrating_nodes.getSize())*sizeof(Real)); return; } const ElementType el_type = _segment_2; const SolidMechanicsModel & model = getModel(); - UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type).values; + UInt * conn_val = model.getFEM().getMesh().getConnectivity(el_type, _not_ghost).values; const UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); const UInt dim = 2; - + + Vector & projected_positions = *pen_list.projected_positions(el_type, _not_ghost); + Real * vel_val = model.getVelocity().values; Real * mass_val = model.getMass().values; Real * v_n = vel_norm.values; - Real * v_f = vel_fric.values; + Real * v_f = vel_fric.values; UInt * index = nodes_index.values; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) { // for (UInt el = pen_list.penetrated_facets_offset[el_type]->values[n]; el < pen_list.penetrated_facets_offset[el_type]->values[n+1]; ++el) { - const Real h[3] = {1.-pen_list.projected_positions[el_type]->values[n], - pen_list.projected_positions[el_type]->values[n], -1.}; - Real temp[3] = {0., 0., 0.}; + const Real h[3] = {1.-projected_positions(n), + projected_positions(n), -1.}; + Real temp[3] = {0., 0., 0.}; - for (UInt i=0; i<3; ++i) { - temp[0] += h[i]*vel_val[dim*index[i+3*n]]; - temp[1] += h[i]*vel_val[dim*index[i+3*n]+1]; - temp[2] += h[i]*h[i]/mass_val[index[i+3*n]]; - } + for (UInt i=0; i<3; ++i) { + temp[0] += h[i]*vel_val[dim*index[i+3*n]]; + temp[1] += h[i]*vel_val[dim*index[i+3*n]+1]; + temp[2] += h[i]*h[i]/mass_val[index[i+3*n]]; + } - /// Compute non-fixed components of velocities - for (UInt i=0; i<2; ++i) - for (UInt j=0; j<3; ++j) - v_f[n*6+j*dim+i] = temp[i]*h[j]/(temp[2]*mass_val[index[3*n+j]]); - - /// Compute slide components of velocities - for (UInt i=0; i<6; ++i) - v_f[n*6+i] = v_f[n*6+i] - v_n[n*6+i]; + /// Compute non-fixed components of velocities + for (UInt i=0; i<2; ++i) + for (UInt j=0; j<3; ++j) + v_f[n*6+j*dim+i] = temp[i]*h[j]/(temp[2]*mass_val[index[3*n+j]]); - /// Compute final friction velocities */ - memset(temp, 0, 3*sizeof(Real)); - for (UInt i=0; i<3; ++i) - for (UInt j = 0; j < dim; ++j) { + /// Compute slide components of velocities + for (UInt i=0; i<6; ++i) + v_f[n*6+i] = v_f[n*6+i] - v_n[n*6+i]; + + /// Compute final friction velocities */ + memset(temp, 0, 3*sizeof(Real)); + for (UInt i=0; i<3; ++i) + for (UInt j = 0; j < dim; ++j) { temp[0] += v_n[n*6+i*dim+j]*v_n[n*6+i*dim+j]/mass_val[index[3*n+i]]; temp[1] += v_f[n*6+i*dim+j]*v_f[n*6+i*dim+j]/mass_val[index[3*n+i]]; } - Real mu = sqrt(temp[0]/temp[1])*getFrictionCoefficient(); + Real mu = sqrt(temp[0]/temp[1])*getFrictionCoefficient(); - if (mu < 1.) - for (UInt i=0; i<6; ++i) - v_f[i] *= mu; + if (mu < 1.) + for (UInt i=0; i<6; ++i) + v_f[i] *= mu; // } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Contact2dExplicit::updatePostImpactVelocities(PenetrationList & pen_list, Vector & nodes_index, Vector & vel_norm, Vector & vel_fric) { AKANTU_DEBUG_IN(); const UInt dim = 2; - + Real * v = model.getVelocity().values; Real * v_n = vel_norm.values; Real * v_f = vel_fric.values; UInt * index = nodes_index.values; /// Loop over projected nodes for (UInt n = 0; n < pen_list.penetrating_nodes.getSize(); ++n) for (UInt i = 0; i < 3; ++i) for (UInt j = 0; j < dim; ++j) v[dim*index[3*n+i]+j] -= ((1.+coefficient_of_restitution)*v_n[n*6+dim*i+j] + v_f[n*6+dim*i+j]); AKANTU_DEBUG_OUT(); } -__END_AKANTU__ +__END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_rigid.cc b/model/solid_mechanics/contact/contact_rigid.cc index 5508a29ac..9ffba6b67 100644 --- a/model/solid_mechanics/contact/contact_rigid.cc +++ b/model/solid_mechanics/contact/contact_rigid.cc @@ -1,1129 +1,1129 @@ /** * @file contact_rigid.cc * @author David Kammer * @date Tue Oct 26 17:15:08 2010 * * @brief Specialization of the contact structure for 3d contact in explicit * time scheme * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_rigid.hh" #include "contact_search.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactRigid::ImpactorInformationPerMaster::ImpactorInformationPerMaster(const Surface master_id, const UInt spatial_dimension) : master_id(master_id) { AKANTU_DEBUG_IN(); this->impactor_surfaces = new std::vector(0); this->active_impactor_nodes = new Vector(0,1); //this->master_element_offset = new Vector(0,1); this->master_element_type = new std::vector(0); this->master_normals = new Vector(0, spatial_dimension); this->node_is_sticking = new Vector(0,2); this->friction_forces = new Vector(0,spatial_dimension); this->stick_positions = new Vector(0,spatial_dimension); this->residual_forces = new Vector(0,spatial_dimension); this->previous_velocities = new Vector(0,spatial_dimension); - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactRigid::ImpactorInformationPerMaster::~ImpactorInformationPerMaster() { AKANTU_DEBUG_IN(); - delete this->impactor_surfaces; + delete this->impactor_surfaces; delete this->active_impactor_nodes; // delete this->master_element_offset; delete this->master_element_type; delete this->master_normals; delete this->node_is_sticking; delete this->friction_forces; delete this->stick_positions; delete this->residual_forces; delete this->previous_velocities; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactRigid::ContactRigid(const SolidMechanicsModel & model, const ContactType & type, const ContactID & id, const MemoryID & memory_id) : Contact(model, type, id, memory_id), spatial_dimension(model.getSpatialDimension()), mesh(model.getFEM().getMesh()) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactRigid::~ContactRigid() { AKANTU_DEBUG_IN(); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; for (it_imp = this->impactors_information.begin(); it_imp != this->impactors_information.end(); ++it_imp) { delete it_imp->second; } this->impactors_information.clear(); this->friction_coefficient.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::addMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); Contact::addMasterSurface(master_surface); ImpactorInformationPerMaster * impactor_info = new ImpactorInformationPerMaster(master_surface, this->spatial_dimension); this->impactors_information[master_surface] = impactor_info; - + //this->friction_coefficient[master_surface] = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::addImpactorSurfaceToMasterSurface(const Surface & impactor_surface, const Surface & master_surface) { AKANTU_DEBUG_IN(); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master_surface); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map"); it_imp->second->impactor_surfaces->push_back(impactor_surface); /* for (UInt m=0; m < this->impactors_information.size(); ++m) { if (this->impactors_information.at(m)->master_id == master_surface) { this->impactors_information.at(m)->impactor_surfaces->push_back(impactor_surface); break; } } */ ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master_surface); if (it_fc != this->friction_coefficient.end()) it_fc->second->addImpactorSurface(impactor_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::removeMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); Contact::removeMasterSurface(master_surface); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master_surface); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map"); delete it_imp->second; this->impactors_information.erase(it_imp); ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master_surface); - AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), + AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), "The master surface: " << master_surface << "couldn't be found and erased in friction_coefficient map"); this->friction_coefficient.erase(it_fc); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::removeImpactorSurfaceFromMasterSurface(const Surface & impactor_surface, const Surface & master_surface) { AKANTU_DEBUG_IN(); - - // find in map the impactor information for the given master surface + + // find in map the impactor information for the given master surface ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master_surface); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master_surface << "couldn't be found and erased in impactors_information map"); std::vector * imp_surfaces = it_imp->second->impactor_surfaces; - + // find and delete the impactor surface std::vector::iterator it_surf; it_surf = find(imp_surfaces->begin(), imp_surfaces->end(), impactor_surface); AKANTU_DEBUG_ASSERT(it_surf != imp_surfaces->end(), "Couldn't find impactor surface " << impactor_surface << " for the master surface " << master_surface << " and couldn't erase it"); imp_surfaces->erase(it_surf); /* for (UInt m=0; m < this->impactors_information.size(); ++m) { ImpactorInformationPerMaster * impactor_info = this->impactors_information.at(m); if (impactor_info->master_id == master_surface) { for (UInt i=0; i < impactor_info->impactor_surfaces->size(); ++i) { Surface imp_surface = impactor_info->impactor_surfaces->at(i); if (imp_surface == impactor_surface) { impactor_info->impactor_surfaces->erase(impactor_info->impactor_surfaces->begin()+i); break; } } } } */ - + ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master_surface); if (it_fc != this->friction_coefficient.end()) it_fc->second->removeImpactorSurface(impactor_surface); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::solveContact() { AKANTU_DEBUG_IN(); for(UInt m=0; m < master_surfaces.size(); ++m) { Surface master = this->master_surfaces.at(m); PenetrationList * penet_list = new PenetrationList(); contact_search->findPenetration(master, *penet_list); solvePenetrationClosestProjection(master, *penet_list); delete penet_list; } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /*void ContactRigid::solvePenetration(const PenetrationList & penet_list) { AKANTU_DEBUG_IN(); const UInt dim = ; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_types = type_list.size(); UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; - + for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; } } Real * current_position = model.getCurrentPosition().values; Real * displacement = model.getDisplacement().values; Real * increment = model.getIncrement().values; UInt * penetrating_nodes = penet_list.penetrating_nodes.values; for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) { UInt current_node = penetrating_nodes[n]; - + // count number of elements penetrated by this node UInt nb_penetrated_facets = 0; ElementType penetrated_type; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; UInt offset_min = penet_list.penetrated_facets_offset[type].get(n); UInt offset_max = penet_list.penetrated_facets_offset[type].get(n+1); nb_penetrated_facets += offset_max - offset_min; penetrated_type = type; } // easy case: node penetrated only one facet if(nb_penetrated_facets == 1) { Real * facets_normals = penet_list.facets_normals[penetrated_type].values; Real * gaps = penet_list.gaps[penetrated_type].values; Real * projected_positions = penet_list.projected_positions[penetrated_type].values; UInt offset_min = penet_list.penetrated_facets_offset[penetrated_type].get(n); for(UInt i=0; i < dim; ++i) { current_position[current_node*dim + i] = projected_positions[offset_min*dim + i]; Real displacement_correction = gaps[offset_min*dim + i] * normals[offset_min*dim + i]; displacement[current_node*dim + i] = displacement[current_node*dim + i] - displacement_correction; increment [current_node*dim + i] = increment [current_node*dim + i] - displacement_correction; } } - + // if more penetrated facets, find the one from which the impactor node is coming else { } } }*/ /* -------------------------------------------------------------------------- */ -void ContactRigid::solvePenetrationClosestProjection(const Surface master, +void ContactRigid::solvePenetrationClosestProjection(const Surface master, const PenetrationList & penet_list) { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; - + for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; } } for (UInt n=0; n < penet_list.penetrating_nodes.getSize(); ++n) { - + // find facet for which the gap is the smallest Real min_gap = std::numeric_limits::max(); ElementType penetrated_type; UInt penetrated_facet_offset; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; - Real * gaps = penet_list.gaps[type]->values; - UInt offset_min = penet_list.penetrated_facets_offset[type]->get(n); - UInt offset_max = penet_list.penetrated_facets_offset[type]->get(n+1); + Real * gaps = penet_list.gaps(type, _not_ghost)->values; + UInt offset_min = penet_list.penetrated_facets_offset(type, _not_ghost)->get(n); + UInt offset_max = penet_list.penetrated_facets_offset(type, _not_ghost)->get(n+1); for (UInt f = offset_min; f < offset_max; ++f) { if(gaps[f] < min_gap) { min_gap = gaps[f]; penetrated_type = type; penetrated_facet_offset = f; } } } bool is_active = isAlreadyActiveImpactor(master, penet_list, n, penetrated_type, penetrated_facet_offset); if (!is_active) { // correct the position of the impactor projectImpactor(penet_list, n, penetrated_type, penetrated_facet_offset); lockImpactorNode(master, penet_list, n, penetrated_type, penetrated_facet_offset); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -bool ContactRigid::isAlreadyActiveImpactor(const Surface master, - const PenetrationList & penet_list, - const UInt impactor_index, - const ElementType facet_type, +bool ContactRigid::isAlreadyActiveImpactor(const Surface master, + const PenetrationList & penet_list, + const UInt impactor_index, + const ElementType facet_type, const UInt facet_offset) { AKANTU_DEBUG_IN(); bool is_active = false; UInt * penetrating_nodes = penet_list.penetrating_nodes.values; UInt impactor_node = penetrating_nodes[impactor_index]; // find facet normal - Real * facets_normals = penet_list.facets_normals[facet_type]->values; + Real * facets_normals = penet_list.facets_normals(facet_type, _not_ghost)->values; Real * facet_normal = &facets_normals[facet_offset*spatial_dimension]; Int normal[this->spatial_dimension]; for(UInt i = 0; i < this->spatial_dimension; ++i) normal[i] = static_cast(floor(facet_normal[i] + 0.5)); - + // check if this is already in the active impactor node list ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; Vector * active_nodes = impactor_info->active_impactor_nodes; Vector * master_normals = impactor_info->master_normals; for (UInt i=0; igetSize(); ++i) { if(active_nodes->at(i) == impactor_node) { UInt count = 0; for (UInt d=0; dspatial_dimension; ++d) { if(master_normals->at(i,d) == normal[d]) count++; } if(count == this->spatial_dimension) is_active = true; } } AKANTU_DEBUG_OUT(); return is_active; } /* -------------------------------------------------------------------------- */ void ContactRigid::projectImpactor(const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset) { AKANTU_DEBUG_IN(); - + const bool increment_flag = model.getIncrementFlag(); UInt * penetrating_nodes = penet_list.penetrating_nodes.values; - Real * facets_normals = penet_list.facets_normals[facet_type]->values; - Real * gaps = penet_list.gaps[facet_type]->values; - Real * projected_positions = penet_list.projected_positions[facet_type]->values; + Real * facets_normals = penet_list.facets_normals(facet_type, _not_ghost)->values; + Real * gaps = penet_list.gaps(facet_type, _not_ghost)->values; + Real * projected_positions = penet_list.projected_positions(facet_type, _not_ghost)->values; Real * current_position = model.getCurrentPosition().values; Real * displacement = model.getDisplacement().values; Real * increment = NULL; if(increment_flag) increment = model.getIncrement().values; UInt impactor_node = penetrating_nodes[impactor_index]; for(UInt i=0; i < this->spatial_dimension; ++i) { current_position[impactor_node*spatial_dimension + i] = projected_positions[facet_offset*spatial_dimension + i]; Real displacement_correction = gaps[facet_offset] * facets_normals[facet_offset*spatial_dimension + i]; displacement[impactor_node*spatial_dimension + i] = displacement[impactor_node*spatial_dimension + i] - displacement_correction; if(increment_flag) increment [impactor_node*spatial_dimension + i] = increment [impactor_node*spatial_dimension + i] - displacement_correction; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::lockImpactorNode(const Surface master, const PenetrationList & penet_list, const UInt impactor_index, const ElementType facet_type, const UInt facet_offset) { AKANTU_DEBUG_IN(); - + bool init_state_stick = true; // node is in sticking when it gets in contact UInt * penetrating_nodes = penet_list.penetrating_nodes.values; UInt impactor_node = penetrating_nodes[impactor_index]; - Real * facets_normals = penet_list.facets_normals[facet_type]->values; + Real * facets_normals = penet_list.facets_normals(facet_type, _not_ghost)->values; Real * facet_normal = &facets_normals[facet_offset*spatial_dimension]; Real normal[this->spatial_dimension]; //Int * normal_val = &normal[0]; bool * bound_val = this->model.getBoundary().values; Real * position_val = this->model.getCurrentPosition().values; Real * veloc_val = this->model.getVelocity().values; Real * accel_val = this->model.getAcceleration().values; Real * residual_val = this->model.getResidual().values; for(UInt i = 0; i < this->spatial_dimension; ++i) normal[i] = floor(facet_normal[i] + 0.5); - + for(UInt i = 0; i < this->spatial_dimension; ++i) { UInt index = impactor_node * spatial_dimension + i; if(normal[i] != 0) { bound_val[index] = true; veloc_val[index] = 0.; accel_val[index] = 0.; } // if node is in initial stick its tangential velocity has to be zero if(init_state_stick) { veloc_val[index] = 0.; accel_val[index] = 0.; } } ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; impactor_info->active_impactor_nodes->push_back(impactor_node); // impactor_info->master_element_offset->push_back(facet_offset); impactor_info->master_element_type->push_back(facet_type); impactor_info->master_normals->push_back(normal); // initial value for stick state when getting in contact bool init_sticking[2]; if (init_state_stick) { - init_sticking[0] = true; + init_sticking[0] = true; init_sticking[1] = true; } else { - init_sticking[0] = false; + init_sticking[0] = false; init_sticking[1] = false; } impactor_info->node_is_sticking->push_back(init_sticking); Real init_friction_force[this->spatial_dimension]; for(UInt i=0; ispatial_dimension; ++i) { init_friction_force[i] = 0.; } impactor_info->friction_forces->push_back(init_friction_force); impactor_info->stick_positions->push_back(&(position_val[impactor_node*this->spatial_dimension])); impactor_info->residual_forces->push_back(&(residual_val[impactor_node*this->spatial_dimension])); impactor_info->previous_velocities->push_back(&(veloc_val[impactor_node*this->spatial_dimension])); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::avoidAdhesion() { AKANTU_DEBUG_IN(); Real * residual_val = this->model.getResidual().values; bool * bound_val = this->model.getBoundary().values; for(UInt m=0; m < this->master_surfaces.size(); ++m) { Surface master = this->master_surfaces.at(m); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; for (UInt n=0; n < impactor_info->active_impactor_nodes->getSize(); ++n) { UInt current_node = impactor_info->active_impactor_nodes->at(n); - + for (UInt i=0; i < spatial_dimension; ++i) { Int direction = impactor_info->master_normals->at(n,i); Real force = residual_val[current_node * spatial_dimension + i]; if(force * direction > 0.) { bound_val[current_node * spatial_dimension + i] = false; impactor_info->active_impactor_nodes->erase(n); // impactor_info->master_element_offset->erase(n); impactor_info->master_element_type->erase(impactor_info->master_element_type->begin()+n); impactor_info->master_normals->erase(n); impactor_info->node_is_sticking->erase(n); impactor_info->friction_forces->erase(n); impactor_info->stick_positions->erase(n); impactor_info->residual_forces->erase(n); impactor_info->previous_velocities->erase(n); n--; break; } } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::frictionPredictor() { AKANTU_DEBUG_IN(); - + const Real null_tolerance = std::numeric_limits::epsilon() * 2.; - + Real * residual_val = this->model.getResidual().values; Real * acceleration_val = this->model.getAcceleration().values; Real * velocity_val = this->model.getVelocity().values; - + for(UInt m=0; m < this->master_surfaces.size(); ++m) { Surface master = this->master_surfaces.at(m); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master); - AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), + AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), "The master surface: " << master << "couldn't be found in friction_coefficient map"); FrictionCoefficient * fric_coef = it_fc->second; AKANTU_DEBUG_ASSERT(fric_coef != NULL, "There is no friction coefficient defined for master surface " << master); UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize(); // compute the friction coefficient for each active impactor node Vector friction_coefficient_values(nb_active_impactor_nodes, 1); Real * friction_coefficient_values_p = friction_coefficient_values.values; fric_coef->computeFrictionCoefficient(friction_coefficient_values); - + UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->values; Real * direction_val = impactor_info->master_normals->values; bool * node_is_sticking_val = impactor_info->node_is_sticking->values; Real * friction_forces_val = impactor_info->friction_forces->values; Real * residual_forces_val = impactor_info->residual_forces->values; Real * previous_velocities_val = impactor_info->previous_velocities->values; - + for (UInt n=0; n < nb_active_impactor_nodes; ++n) { UInt current_node = active_impactor_nodes_val[n]; - + // save original residual for(UInt i=0; i < spatial_dimension; ++i) { residual_forces_val[n*spatial_dimension+i] = residual_val[current_node*spatial_dimension+i]; } - + // find friction force mu * normal force Real normal_contact_force = 0.; Real friction_force = 0.; for (UInt i=0; i < spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] != 0) { normal_contact_force = fabs(residual_val[current_node * this->spatial_dimension + i]); friction_force = friction_coefficient_values_p[n] * normal_contact_force; } } // if node is sticking, friction force acts against the residual if (node_is_sticking_val[n*2]) { // compute length of projected residual Real projected_residual = 0.; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { - projected_residual += residual_val[current_node * this->spatial_dimension + i] * - residual_val[current_node * this->spatial_dimension + i]; + projected_residual += residual_val[current_node * this->spatial_dimension + i] * + residual_val[current_node * this->spatial_dimension + i]; } } projected_residual = sqrt(projected_residual); // friction is weaker than residual -> start sliding if (friction_force < projected_residual) { node_is_sticking_val[n*2] = false; node_is_sticking_val[n*2+1] = false; // compute friction vector Real friction_direction[3]; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { friction_direction[i] = residual_val[current_node * this->spatial_dimension + i]; friction_direction[i] /= projected_residual; } else friction_direction[i] = 0.; friction_direction[i] *= -1.; } - + // add friction force to residual for (UInt i=0; i < this->spatial_dimension; ++i) { Real directional_fric_force = friction_force * friction_direction[i]; friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force; residual_val[current_node * this->spatial_dimension + i] += directional_fric_force; } } // friction is stronger than residual -> stay sticking else { // put residual in friction force and set residual to zero for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { friction_forces_val[n*spatial_dimension + i] = residual_val[current_node * this->spatial_dimension + i]; residual_val[current_node * this->spatial_dimension + i] = 0.; } else friction_forces_val[n*spatial_dimension + i] = 0.; friction_forces_val[n*spatial_dimension + i] *= -1.; } } } // end if stick - - + + // if node is sliding friction force acts against velocity and // in case there is no velocity it acts against the residual else { Real projected_residual = 0.; Real projected_velocity_magnitude = 0.; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { - projected_residual += residual_val[current_node * this->spatial_dimension + i] * - residual_val[current_node * this->spatial_dimension + i]; + projected_residual += residual_val[current_node * this->spatial_dimension + i] * + residual_val[current_node * this->spatial_dimension + i]; projected_velocity_magnitude += previous_velocities_val[n * this->spatial_dimension + i] * - previous_velocities_val[n * this->spatial_dimension + i]; + previous_velocities_val[n * this->spatial_dimension + i]; } } projected_residual = sqrt(projected_residual); projected_velocity_magnitude = sqrt(projected_velocity_magnitude); - + // if no projected velocity nor friction force stronger than projected residual, this is stick if ((projected_velocity_magnitude < null_tolerance) && !(projected_residual > friction_force)) { // put residual in friction force and set residual to zero // set projected velocity and acceleration to zero for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { friction_forces_val[n*spatial_dimension + i] = residual_val[current_node * this->spatial_dimension + i]; residual_val [current_node * this->spatial_dimension + i] = 0.; velocity_val [current_node * this->spatial_dimension + i] = 0.; acceleration_val[current_node * this->spatial_dimension + i] = 0.; } else friction_forces_val[n*spatial_dimension + i] = 0.; friction_forces_val[n*spatial_dimension + i] *= -1.; } node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true; } // node is really sliding - else { + else { UInt index = 0; Real * direction_vector; Real direction_length; // if only velocity is zero (because slider just turned direction) if (projected_velocity_magnitude < null_tolerance) { index = current_node; direction_vector = residual_val; direction_length = projected_residual; } // there is velocity else { index = n; direction_vector = previous_velocities_val; direction_length = projected_velocity_magnitude; } // compute the friction direction - Real friction_direction[3]; + Real friction_direction[3]; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { friction_direction[i] = direction_vector[index * this->spatial_dimension + i]; friction_direction[i] /= direction_length; } else friction_direction[i] = 0.; friction_direction[i] *= -1.; } - + // add friction force to residual for (UInt i=0; i < this->spatial_dimension; ++i) { Real directional_fric_force = friction_force * friction_direction[i]; friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force; residual_val[current_node * this->spatial_dimension + i] += directional_fric_force; } } } // end sliding } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::frictionCorrector() { AKANTU_DEBUG_IN(); - + const Real tolerance = std::numeric_limits::epsilon() * 100.; - + Real * residual_val = this->model.getResidual().values; Real * acceleration_val = this->model.getAcceleration().values; Real * velocity_val = this->model.getVelocity().values; - + for(UInt m=0; m < this->master_surfaces.size(); ++m) { Surface master = this->master_surfaces.at(m); ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize(); UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->values; Real * direction_val = impactor_info->master_normals->values; bool * node_is_sticking_val = impactor_info->node_is_sticking->values; Real * friction_forces_val = impactor_info->friction_forces->values; Real * residual_forces_val = impactor_info->residual_forces->values; Real * previous_velocities_val = impactor_info->previous_velocities->values; - + for (UInt n=0; n < nb_active_impactor_nodes; ++n) { UInt current_node = active_impactor_nodes_val[n]; // check only sliding impactor nodes if (node_is_sticking_val[n*2]) continue; // compute scalar product of previous velocity with current velocity Real dot_prod_velocities = 0.; Real current_proj_vel_mag = 0.; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { - dot_prod_velocities += velocity_val[current_node * this->spatial_dimension + i] * - previous_velocities_val[n * this->spatial_dimension + i]; + dot_prod_velocities += velocity_val[current_node * this->spatial_dimension + i] * + previous_velocities_val[n * this->spatial_dimension + i]; current_proj_vel_mag += velocity_val[current_node * this->spatial_dimension + i] * - velocity_val[current_node * this->spatial_dimension + i]; + velocity_val[current_node * this->spatial_dimension + i]; } } current_proj_vel_mag = sqrt(current_proj_vel_mag); - + // if velocity has changed sign or has become very small we get into stick if ((dot_prod_velocities < 0.) || (current_proj_vel_mag < tolerance)) { // compute scalar product of residual and current velocity Real dot_prod_vel_res = 0.; Real proj_friction_mag = 0.; Real proj_residual_mag = 0.; for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { - dot_prod_vel_res += residual_forces_val[n * this->spatial_dimension + i] * - previous_velocities_val[n * this->spatial_dimension + i]; + dot_prod_vel_res += residual_forces_val[n * this->spatial_dimension + i] * + previous_velocities_val[n * this->spatial_dimension + i]; proj_friction_mag += friction_forces_val[n * this->spatial_dimension + i] * - friction_forces_val[n * this->spatial_dimension + i]; + friction_forces_val[n * this->spatial_dimension + i]; proj_residual_mag += residual_forces_val[n * this->spatial_dimension + i] * - residual_forces_val[n * this->spatial_dimension + i]; + residual_forces_val[n * this->spatial_dimension + i]; } } proj_friction_mag = sqrt(proj_friction_mag); proj_residual_mag = sqrt(proj_residual_mag); for (UInt i=0; i < this->spatial_dimension; ++i) { if(direction_val[n * this->spatial_dimension + i] == 0) { //friction_forces_val[n*spatial_dimension + i] = residual_forces_val[n*spatial_dimension + i]; residual_forces_val[n * this->spatial_dimension + i] =0.; residual_val [current_node * this->spatial_dimension + i] = 0.; velocity_val [current_node * this->spatial_dimension + i] = 0.; acceleration_val[current_node * this->spatial_dimension + i] = 0.; } else friction_forces_val[n*spatial_dimension + i] = 0.; friction_forces_val[n*spatial_dimension + i] *= -1.; } node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true; } } - + // save current velocities for (UInt n=0; n < nb_active_impactor_nodes; ++n) { UInt current_node = active_impactor_nodes_val[n]; for(UInt i=0; i < spatial_dimension; ++i) { previous_velocities_val[n*spatial_dimension+i] = velocity_val[current_node*spatial_dimension+i]; } } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::addRegularizedFriction(const Real & regularizer) { AKANTU_DEBUG_IN(); - - AKANTU_DEBUG_ASSERT(this->spatial_dimension == 2, + + AKANTU_DEBUG_ASSERT(this->spatial_dimension == 2, "addRegularizedFriction is implemented only for 2D"); Real * residual_val = this->model.getResidual().values; Real * position_val = this->model.getCurrentPosition().values; - + for(UInt m=0; m < this->master_surfaces.size(); ++m) { Surface master = this->master_surfaces.at(m); // find the impactors information for this master surface ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; // find the friction coefficient object for this master ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master); - AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), + AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), "The master surface: " << master << "couldn't be found in friction_coefficient map"); FrictionCoefficient * fric_coef = it_fc->second; AKANTU_DEBUG_ASSERT(fric_coef != NULL, "There is no friction coefficient defined for master surface " << master); UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize(); // compute the friction coefficient for each active impactor node Vector friction_coefficient_values(nb_active_impactor_nodes, 1); Real * friction_coefficient_values_p = friction_coefficient_values.values; fric_coef->computeFrictionCoefficient(friction_coefficient_values); - + UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->values; Real * direction_val = impactor_info->master_normals->values; bool * node_is_sticking_val = impactor_info->node_is_sticking->values; Real * friction_forces_val = impactor_info->friction_forces->values; Real * stick_positions_val = impactor_info->stick_positions->values; - + for (UInt n=0; n < nb_active_impactor_nodes; ++n) { UInt current_node = active_impactor_nodes_val[n]; Real normal_contact_force = 0.; Real friction_force = 0.; - + // find friction force mu * normal force for (UInt i=0; ispatial_dimension + i] != 0) { normal_contact_force = fabs(residual_val[current_node * this->spatial_dimension + i]); friction_force = friction_coefficient_values_p[n] * normal_contact_force; } } - - // compute F_(i+1)trial + + // compute F_(i+1)trial Real f_trial = Math::distance_2d(&(position_val[current_node * this->spatial_dimension]), &(stick_positions_val[n * this->spatial_dimension])); f_trial *= regularizer; Real delta_s_vector[this->spatial_dimension]; for (UInt i=0; ispatial_dimension + i] - - stick_positions_val[n * this->spatial_dimension + i]; + delta_s_vector[i] = position_val[current_node * this->spatial_dimension + i] + - stick_positions_val[n * this->spatial_dimension + i]; delta_s_vector[i] *= -1.; } // if node is on its own stick position no need to compute friction force // this avoids nan on normalize2 if(Math::norm2(delta_s_vector) < Math::tolerance) { node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true; continue; } Math::normalize2(delta_s_vector); // check if node is still sticking if (f_trial <= friction_force) { friction_force = f_trial; // sticking position stays unchanged node_is_sticking_val[n*2] = true; node_is_sticking_val[n*2+1] = true; } else { node_is_sticking_val[n*2] = false; node_is_sticking_val[n*2+1] = false; Real delta_s = std::abs(f_trial - friction_force) / regularizer; // friction force stays unchanged for (UInt i=0; ispatial_dimension + i] -= delta_s * delta_s_vector[i]; } } - + // add friction force to residual for (UInt i=0; i < this->spatial_dimension; ++i) { Real directional_fric_force = friction_force * delta_s_vector[i]; friction_forces_val[n*this->spatial_dimension + i] = directional_fric_force; residual_val[current_node * this->spatial_dimension + i] += directional_fric_force; } } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::setStickPositionsToCurrentPositions(const Surface master) { AKANTU_DEBUG_IN(); - + Real * position_val = this->model.getCurrentPosition().values; - + // find the impactors information for this master surface ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; - + UInt nb_active_impactor_nodes = impactor_info->active_impactor_nodes->getSize(); UInt * active_impactor_nodes_val = impactor_info->active_impactor_nodes->values; Real * stick_positions_val = impactor_info->stick_positions->values; - + for (UInt n=0; n < nb_active_impactor_nodes; ++n) { UInt current_node = active_impactor_nodes_val[n]; - + // find friction force mu * normal force for (UInt i=0; ispatial_dimension + i] = position_val[current_node*this->spatial_dimension + i]; } } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::setFrictionCoefficient(FrictionCoefficient * fric_coefficient) { AKANTU_DEBUG_IN(); - + Surface master = fric_coefficient->getMasterSurface(); ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master); - AKANTU_DEBUG_ASSERT(it_fc == this->friction_coefficient.end(), + AKANTU_DEBUG_ASSERT(it_fc == this->friction_coefficient.end(), "There is already a friction coefficient for master surface: " << master); this->friction_coefficient[master] = fric_coefficient; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactRigid::removeFrictionCoefficient(const Surface master) { AKANTU_DEBUG_IN(); - + ContactRigid::SurfaceToFricCoefMap::iterator it_fc; it_fc = this->friction_coefficient.find(master); - AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), + AKANTU_DEBUG_ASSERT(it_fc != this->friction_coefficient.end(), "There is no friction coefficient for master surface: " << master); this->friction_coefficient.erase(it_fc); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactRigid::getRestartInformation(std::map & map_to_fill, +void ContactRigid::getRestartInformation(std::map & map_to_fill, Surface master) { AKANTU_DEBUG_IN(); - + ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; UInt nb_active_nodes = impactor_info->active_impactor_nodes->getSize(); // create vectors Vector * activity_of_nodes = new Vector(this->mesh.getNbNodes(), 1, false); - Vector * element_type_of_nodes = new Vector(this->mesh.getNbNodes(), 1, _not_defined); + Vector * element_type_of_nodes = new Vector(this->mesh.getNbNodes(), 1, _not_defined); Vector * normals_of_nodes = new Vector(this->mesh.getNbNodes(), this->spatial_dimension, 0.); Vector * sticking_of_nodes = new Vector(this->mesh.getNbNodes(), 2, false); Vector * friction_force_of_nodes = new Vector(this->mesh.getNbNodes(), this->spatial_dimension, 0.); Vector * stick_position_of_nodes = new Vector(this->mesh.getNbNodes(), this->spatial_dimension, 0.); Vector * residual_force_of_nodes = new Vector(this->mesh.getNbNodes(), this->spatial_dimension, 0.); Vector * previous_velocity_of_nodes = new Vector(this->mesh.getNbNodes(), this->spatial_dimension, 0.); UInt * active_nodes = impactor_info->active_impactor_nodes->values; - ElementType * element_type = &(*impactor_info->master_element_type)[0]; + ElementType * element_type = &(*impactor_info->master_element_type)[0]; Real * master_normal = impactor_info->master_normals->values; bool * node_stick = impactor_info->node_is_sticking->values; Real * friction_force = impactor_info->friction_forces->values; Real * stick_position = impactor_info->stick_positions->values; Real * residual_force = impactor_info->residual_forces->values; Real * previous_velocity = impactor_info->previous_velocities->values; for (UInt i=0; ispatial_dimension; ++d, ++master_normal, ++friction_force, ++stick_position, ++residual_force, ++previous_velocity) { (*normals_of_nodes)(*active_nodes,d) = *master_normal; (*friction_force_of_nodes)(*active_nodes,d) = *friction_force; (*stick_position_of_nodes)(*active_nodes,d) = *stick_position; (*residual_force_of_nodes)(*active_nodes,d) = *residual_force; (*previous_velocity_of_nodes)(*active_nodes,d) = *previous_velocity; } for (UInt j=0; j<2; ++j, ++node_stick) { (*sticking_of_nodes)(*active_nodes,j) = *node_stick; } } map_to_fill["active_impactor_nodes"] = activity_of_nodes; map_to_fill["master_element_type"] = element_type_of_nodes; map_to_fill["master_normals"] = normals_of_nodes; map_to_fill["node_is_sticking"] = sticking_of_nodes; map_to_fill["friction_forces"] = friction_force_of_nodes; map_to_fill["stick_positions"] = stick_position_of_nodes; map_to_fill["residual_forces"] = residual_force_of_nodes; map_to_fill["previous_velocities"] = previous_velocity_of_nodes; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void ContactRigid::setRestartInformation(std::map & restart_map, +void ContactRigid::setRestartInformation(std::map & restart_map, Surface master) { AKANTU_DEBUG_IN(); - + ContactRigid::SurfaceToImpactInfoMap::iterator it_imp; it_imp = this->impactors_information.find(master); - AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), + AKANTU_DEBUG_ASSERT(it_imp != this->impactors_information.end(), "The master surface: " << master << "couldn't be found in impactors_information map"); ImpactorInformationPerMaster * impactor_info = it_imp->second; std::map < std::string, VectorBase* >::iterator it; - + it = restart_map.find("active_impactor_nodes"); Vector * ai_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry for active impactor nodes" << std::endl; } it = restart_map.find("master_element_type"); Vector * et_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry master element type" << std::endl; } it = restart_map.find("master_normals"); Vector * mn_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry for master normals" << std::endl; } it = restart_map.find("node_is_sticking"); Vector * is_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry node is sticking" << std::endl; } it = restart_map.find("friction_forces"); Vector * ff_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry friction forces" << std::endl; } it = restart_map.find("stick_positions"); Vector * sp_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry stick positions" << std::endl; } it = restart_map.find("residual_forces"); Vector * rf_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry residual forces" << std::endl; } it = restart_map.find("previous_velocities"); Vector * pv_nodes = (Vector *)(it->second); if(it == restart_map.end()) { std::cout << "could not find map entry previous" << std::endl; } UInt nb_nodes = this->mesh.getNbNodes(); for (UInt i=0; iactive_impactor_nodes->push_back(i); impactor_info->master_element_type->push_back((*et_nodes)(i)); // get master_normals and friction_forces information Real normal[this->spatial_dimension]; Real friction[this->spatial_dimension]; Real position[this->spatial_dimension]; Real residual[this->spatial_dimension]; Real velocity[this->spatial_dimension]; for (UInt d=0; dspatial_dimension; ++d) { normal[d] = (*mn_nodes)(i,d); friction[d] = (*ff_nodes)(i,d); position[d] = (*sp_nodes)(i,d); residual[d] = (*rf_nodes)(i,d); velocity[d] = (*pv_nodes)(i,d); } impactor_info->master_normals->push_back(normal); impactor_info->friction_forces->push_back(friction); impactor_info->stick_positions->push_back(position); impactor_info->residual_forces->push_back(residual); impactor_info->previous_velocities->push_back(velocity); // get node_is_sticking information bool stick[2]; for (UInt j=0; j<2; ++j) { stick[j] = (*is_nodes)(i,j); } impactor_info->node_is_sticking->push_back(stick); } } - + AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_search_2d_explicit.cc b/model/solid_mechanics/contact/contact_search_2d_explicit.cc index ef057eacd..9e9c2df51 100755 --- a/model/solid_mechanics/contact/contact_search_2d_explicit.cc +++ b/model/solid_mechanics/contact/contact_search_2d_explicit.cc @@ -1,421 +1,425 @@ /** * @file contact_search_2d_explicit.cc * @author Leonardo Snozzi * @date Wed Nov 3 15:06:52 2010 * - * @brief Contact + * @brief Contact * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_search_2d_explicit.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "aka_memory.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactSearch2dExplicit::ContactSearch2dExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : ContactSearch(contact, neighbors_structure_type, type, id) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch2dExplicit::~ContactSearch2dExplicit() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch2dExplicit::findPenetration(const Surface & master_surface, PenetrationList & pen_list) { AKANTU_DEBUG_IN(); //const ContactNeighborStructureType & neighbor_type = getContactNeighborStructureType(); const ContactNeighborStructure & structure = getContactNeighborStructure(master_surface); const NeighborList & neigh_list = const_cast(structure).getNeighborList(); // Real * inc_val = contact.getModel().getIncrement().values; // Real * disp_val = contact.getModel().getDisplacement().values; // Real * vel_val = contact.getModel().getVelocity().values; const Contact & contact = getContact(); Real * pos_val = contact.getModel().getCurrentPosition().values; //contact.getModel().updateCurrentPosition(); /// compute current_position = initial_position + displacement temp // Real * coord = contact.getModel().getFEM().getMesh().getNodes().values; // Real * disp = contact.getModel().getDisplacement().values; // Real * pos_val = new Real[contact.getModel().getFEM().getMesh().getNodes().getSize()]; - // for (UInt n = 0; n < contact.getModel().getFEM().getMesh().getNodes().getSize(); ++n) + // for (UInt n = 0; n < contact.getModel().getFEM().getMesh().getNodes().getSize(); ++n) // pos_val[n] = coord[n] + disp[n]; Mesh & mesh = contact.getModel().getFEM().getMesh(); ElementType el_type = _segment_2; /* Only linear element at the moment */ const ContactSearchID & id = getID(); /// Alloc space for Penetration class members std::stringstream sstr_pfo; sstr_pfo << id << ":penetrated_facets_offset:" << el_type; - pen_list.penetrated_facets_offset[el_type] = new Vector(0, 1, sstr_pfo.str()); + pen_list.penetrated_facets_offset(el_type, _not_ghost) = new Vector(0, 1, sstr_pfo.str()); + std::stringstream sstr_pf; sstr_pf << id << ":penetrated_facet:" << el_type; - pen_list.penetrated_facets[el_type] = new Vector(0 ,1, sstr_pf.str()); + pen_list.penetrated_facets(el_type, _not_ghost) = new Vector(0 ,1, sstr_pf.str()); + std::stringstream sstr_fn; sstr_fn << id << ":facet_normals:" << el_type; - pen_list.facets_normals[el_type] = new Vector(0, 2, sstr_fn.str()); + pen_list.facets_normals(el_type, _not_ghost) = new Vector(0, 2, sstr_fn.str()); + std::stringstream sstr_g; sstr_g << id << ":gaps:" << el_type; - pen_list.gaps[el_type] = new Vector(0, 1, sstr_g.str()); + pen_list.gaps(el_type, _not_ghost) = new Vector(0, 1, sstr_g.str()); + std::stringstream sstr_pp; sstr_pp << id << ":projected_positions:" << el_type; - pen_list.projected_positions[el_type] = new Vector(0, 1, sstr_pp.str()); + pen_list.projected_positions(el_type, _not_ghost) = new Vector(0, 1, sstr_pp.str()); //pen_list.nb_nodes = 0; - UInt * facets_off_val = neigh_list.facets_offset[el_type]->values; - UInt * facets_val = neigh_list.facets[el_type]->values; + UInt * facets_off_val = neigh_list.facets_offset(el_type, _not_ghost)->values; + UInt * facets_val = neigh_list.facets(el_type, _not_ghost)->values; - UInt * node_to_el_off_val = contact.getNodeToElementsOffset(el_type).values; - UInt * node_to_el_val = contact.getNodeToElements(el_type).values; + UInt * node_to_el_off_val = contact.getNodeToElementsOffset(el_type, _not_ghost).values; + UInt * node_to_el_val = contact.getNodeToElements(el_type, _not_ghost).values; - UInt * conn_val = mesh.getConnectivity(el_type).values; + UInt * conn_val = mesh.getConnectivity(el_type, _not_ghost).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); /// Loop over the impactor nodes to detect possible penetrations for (UInt i = 0; i < neigh_list.impactor_nodes.getSize(); ++i) { UInt i_node = neigh_list.impactor_nodes.values[i]; Real *x3 = &pos_val[i_node*2]; - /// Loop over elements nearby the impactor node + /// Loop over elements nearby the impactor node for (UInt i_el = facets_off_val[i]; i_el < facets_off_val[i+1]; ++i_el) { UInt facet = facets_val[i_el]; Real * x1 = &pos_val[2*conn_val[facet*elem_nodes]]; Real * x2 = &pos_val[2*conn_val[facet*elem_nodes+1]]; Real vec_surf[2]; Real vec_normal[2]; Real vec_dist[2]; Real length = Math::distance_2d(x1, x2); Math::vector_2d(x1, x2, vec_surf); Math::vector_2d(x1, x3, vec_dist); Math::normal2(vec_surf, vec_normal); - + /* Projection normalized over length*/ - Real projection = Math::vectorDot2(vec_surf, vec_dist)/(length*length); + Real projection = Math::vectorDot2(vec_surf, vec_dist)/(length*length); Real gap = Math::vectorDot2(vec_dist, vec_normal); bool find_proj = false; /// Penetration has occurred if(gap < -PEN_TOL) { InterType test_pen = Detect_Intersection(conn_val[facet*elem_nodes], conn_val[facet*elem_nodes+1], i_node, vec_surf, vec_dist, gap); /// Node has intersected segment if(test_pen != _no) { Real proj = Math::vectorDot2(vec_surf, vec_dist)/(length*length); UInt c_facet = facet; /// Projection on neighbor facet which shares to node1 if(test_pen == _node_1 || (test_pen==_yes && proj < 0.-PROJ_TOL)) { // Find index of neighbor facet for (UInt i = node_to_el_off_val[conn_val[facet*elem_nodes]]; i < node_to_el_off_val[conn_val[facet*elem_nodes]+1]; ++i) if(node_to_el_val[i] != facet /* && on same surface? */) { c_facet = node_to_el_val[i]; break; } if(c_facet != facet) { find_proj = checkProjectionAdjacentFacet(pen_list, facet, c_facet, i_node, proj, el_type); if(find_proj == true) break; } if (proj < 0.-PROJ_TOL && test_pen == _node_1) break; } /// Projection on neighbor facet which shares to node2 if(test_pen == _node_2 || (test_pen==_yes && proj > 1.+PROJ_TOL)) { // Find index of neighbor facet for (UInt i = node_to_el_off_val[conn_val[facet*elem_nodes]]; i < node_to_el_off_val[conn_val[facet*elem_nodes]+1]; ++i) if(node_to_el_val[i] != facet /* && on same surface? */) { c_facet = node_to_el_val[i]; break; } if(c_facet != facet) { find_proj = checkProjectionAdjacentFacet(pen_list, facet, c_facet, i_node, proj, el_type); if(find_proj == true) break; } if (proj > 0.+PROJ_TOL && test_pen == _node_2) break; } /// Save data for projection on this facet -> Check if projection outside in solve? - pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); - pen_list.penetrating_nodes.push_back(i_node); - pen_list.penetrated_facets[el_type]->push_back(facet); - pen_list.facets_normals[el_type]->push_back(vec_normal); /* Correct ? */ - pen_list.gaps[el_type]->push_back(gap); - pen_list.projected_positions[el_type]->push_back(proj); + pen_list.penetrated_facets_offset(el_type, _not_ghost)->push_back(pen_list.penetrating_nodes.getSize()); + pen_list.penetrating_nodes.push_back(i_node); + pen_list.penetrated_facets(el_type, _not_ghost)->push_back(facet); + pen_list.facets_normals(el_type, _not_ghost)->push_back(vec_normal); /* Correct ? */ + pen_list.gaps(el_type, _not_ghost)->push_back(gap); + pen_list.projected_positions(el_type, _not_ghost)->push_back(proj); //pen_list.penetrating_nodes.getSize()++; } } } } - pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); + pen_list.penetrated_facets_offset(el_type, _not_ghost)->push_back(pen_list.penetrating_nodes.getSize()); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ InterType ContactSearch2dExplicit::Detect_Intersection(UInt node1, UInt node2, UInt node3, Real *vec_surf, Real *vec_dist, Real gap) { AKANTU_DEBUG_IN(); const Real eps = 1.e-12, /* Tolerance to set discriminant equal to zero */ eps2 = 1e6, /* */ eps3 = 1e-6; /* Tolerance for space intersection "l" outside segment (tolerance for projection) */ // eps4=1e-2; - /* Upper tolerance for time: penetration may occurred in previous time_step but had been not detected */ + /* Upper tolerance for time: penetration may occurred in previous time_step but had been not detected */ const Real eps4 = 1.0001*PEN_TOL/(-gap-PEN_TOL); Real a[2], b[2], c[2], d[2], den, delta, t[2]={-1.,-1.}, l[2]={-1.,-1.}, k, j; Real * inc_val = getContact().getModel().getIncrement().values; - + /* Initialize vectors of Equation to solve : 0 = a + b*l +c*t + d*t*l */ for(UInt i=0; i<2; i++) { a[i] = -vec_dist[i]; b[i] = vec_surf[i]; c[i] = inc_val[2*node3+i]-inc_val[2*node1+i]; d[i] = inc_val[2*node1+i]-inc_val[2*node2+i]; } /* Compute therm of quadratic equation: t²+k*t+j=0 */ k = (a[1]*d[0]+c[1]*b[0]-c[0]*b[1]-d[1]*a[0])/(c[1]*d[0]-d[1]*c[0]); j = (a[1]*b[0]-b[1]*a[0])/(c[1]*d[0]-d[1]*c[0]); if(isnan(k)!=true && isnan(j)!=true) { if(k < 1.e12 && j < 1.e12) { /* Equation quadratic */ /* If quadratic therm smaller than eps*other therm exclude them */ /* Compute discriminant */ delta = k*k-4.*j; /* Compute solution of quadratic equation */ do { /* Ceck if disc<0 */ if(delta < 0.) { if(delta < -eps) return _no; else // delta close to the machine precision -> only one solution /* delta = 0. */ t[0] = -k/2.; break; } /* Discriminant bigger-equal than zero */ t[0] = (-k-getSign(k)*sqrt(delta))/2.; t[1] = (-k+getSign(k)*sqrt(delta))/2.; if(abs(t[1]) < 2.*eps) t[1] = j/t[0]; } while(0); /* Ceck solution */ for(UInt i=0; i<2; i++) if(t[i]>= 0.-eps3 && t[i]<=1.+eps4) { // Within time step l[i] = -(a[0]+c[0]*t[i])/(b[0]+t[i]*d[0]); if(l[i]>= 0.-eps3 && l[i]<= 1.+eps3) { if(/*t[i]<1.-eps &&*/ l[i]>0.+1.e-3 && l[i]<1.-1.e-3) return _yes; else if(l[i]<0.5) { /* Node 3 close at the beginning to node 1*/ return _node_1; } else { /* Node 3 close at the beginning to node 2 */ return _node_2; } } } return _no; } else { /* New Equation: t²+k*t+j=0 -> k*t+j=0*/ t[0]=-(a[1]*b[0]-b[1]*a[0])/(a[1]*d[0]+c[1]*b[0]-c[0]*b[1]-d[1]*a[0]); if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Within time step l[0] = -(a[0]+c[0]*t[0])/(b[0]+t[0]*d[0]); if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) { if(/*t[i]<1.-eps &&*/ l[0]>0.+1.e-3 && l[0]<1.-1.e-3) return _yes; - + else if(l[0]<0.5) /* Node 3 close at the beginning to node 1*/ return _node_1; - + else /* Node 3 close at the beginning to node 2 */ return _node_2; } } return _no; } } else if(abs(c[1]/d[0])>eps2 && abs(c[0]/d[1])>eps2) { /* neglect array d */ den = b[0]*c[1]-b[1]*c[0]; t[0] = (a[0]*b[1]-b[0]*a[1])/den; if(isnan(t[0])) /* Motion parallel */ return _no; /* ? */ /* Check solution */ if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Possible Intersection Within time step l[0] = -(c[1]*a[0]-c[0]*a[1])/den; if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) return _yes; } return _no; } else if(abs(d[0]/c[1])>eps2 && abs(d[1]/c[0])>eps2) { /* neglect array c */ t[0] = -(-a[1]*b[0]+b[1]*a[0])/(d[1]*a[0]-d[0]*a[1]); if(isnan(t[0])) return _no; /* ? */ /* Ceck solution */ if(t[0]>= 0.-eps3 && t[0]<=1.+eps4) { // Possible Intersection Within time step l[0] = -a[0]/(b[0]+t[0]*d[0]); if(l[0]>= 0.-eps3 && l[0]<= 1.+eps3) return _yes; } return _no; } /* Neglect array c and d*/ return _no; /* undefined (either no motion or parallel motion)*/ AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactSearch2dExplicit::checkProjectionAdjacentFacet(PenetrationList & pen_list, UInt facet, UInt c_facet, UInt i_node, Real old_proj, ElementType el_type) { AKANTU_DEBUG_IN(); - - UInt * conn_val = contact.getModel().getFEM().getMesh().getConnectivity(el_type).values; + + UInt * conn_val = contact.getModel().getFEM().getMesh().getConnectivity(el_type, _not_ghost).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); UInt node1 = conn_val[c_facet*elem_nodes]; UInt node2 = conn_val[c_facet*elem_nodes+1]; Real * pos_val = contact.getModel().getCurrentPosition().values; Real * x1 = &pos_val[2*node1]; Real * x2 = &pos_val[2*node2]; - Real * x3 = &pos_val[2*i_node]; + Real * x3 = &pos_val[2*i_node]; Real vec_surf[2]; Real vec_normal[2]; Real vec_dist[2]; Real length = Math::distance_2d(x1, x2); Math::vector_2d(x1, x2, vec_surf); Math::vector_2d(x1, x3, vec_dist); Math::normal2(vec_surf, vec_normal); - + Real gap = Math::vectorDot2(vec_dist, vec_normal); if(gap < 0.-PEN_TOL) { Real proj = Math::vectorDot2(vec_surf, vec_dist)/(length*length); if(proj >= 0. && proj <= 1.) { /* Project on c_facet or node */ - + /// Save data on penetration list if(old_proj < 0. || old_proj > 1.) { /* (project on adjacent segment) */ - - pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); + + pen_list.penetrated_facets_offset(el_type, _not_ghost)->push_back(pen_list.penetrating_nodes.getSize()); pen_list.penetrating_nodes.push_back(i_node); - pen_list.penetrated_facets[el_type]->push_back(c_facet); - pen_list.facets_normals[el_type]->push_back(vec_normal); /* Correct ? */ - pen_list.gaps[el_type]->push_back(gap); - pen_list.projected_positions[el_type]->push_back(proj); + pen_list.penetrated_facets(el_type, _not_ghost)->push_back(c_facet); + pen_list.facets_normals(el_type, _not_ghost)->push_back(vec_normal); /* Correct ? */ + pen_list.gaps(el_type, _not_ghost)->push_back(gap); + pen_list.projected_positions(el_type, _not_ghost)->push_back(proj); //pen_list.penetrating_nodes.getSize()++; return true; } InterType test_pen = Detect_Intersection(node1, node2, i_node, vec_surf, vec_dist, gap); if(test_pen == _no) return false; - + /* project on node (compute new normal) */ Real new_normal[2] = {0.,0.}; if(old_proj < 0.5) { Real * x4 = &pos_val[2*conn_val[elem_nodes*facet+1]]; Math::vector_2d(x1, x4, vec_surf); Math::normal2(vec_surf, vec_normal); // new_normal[0] = -x3[0]+x2[0]; // new_normal[1] = -x3[1]+x2[1]; - pen_list.projected_positions[el_type]->push_back(0.); + pen_list.projected_positions(el_type, _not_ghost)->push_back(0.); gap = Math::distance_2d(x3, x2); } else { Real * x4 = &pos_val[2*conn_val[elem_nodes*facet]]; Math::vector_2d(x4, x2, vec_surf); Math::normal2(vec_surf, vec_normal); // new_normal[0] = -x3[0]+x1[0]; // new_normal[1] = -x3[1]+x1[1]; - pen_list.projected_positions[el_type]->push_back(1.); + pen_list.projected_positions(el_type, _not_ghost)->push_back(1.); gap = Math::distance_2d(x3, x1); } // Real new_gap = sqrt(new_normal[0]*new_normal[0]+new_normal[1]*new_normal[1]); - pen_list.penetrated_facets_offset[el_type]->push_back(pen_list.penetrating_nodes.getSize()); + pen_list.penetrated_facets_offset(el_type, _not_ghost)->push_back(pen_list.penetrating_nodes.getSize()); pen_list.penetrating_nodes.push_back(i_node); - pen_list.penetrated_facets[el_type]->push_back(facet); - pen_list.facets_normals[el_type]->push_back(vec_normal); - pen_list.gaps[el_type]->push_back(gap); + pen_list.penetrated_facets(el_type, _not_ghost)->push_back(facet); + pen_list.facets_normals(el_type, _not_ghost)->push_back(vec_normal); + pen_list.gaps(el_type, _not_ghost)->push_back(gap); //pen_list.penetrating_nodes.getSize()++; return true; } } return false; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/contact_search_explicit.cc b/model/solid_mechanics/contact/contact_search_explicit.cc index 166c24a20..4d956cb84 100644 --- a/model/solid_mechanics/contact/contact_search_explicit.cc +++ b/model/solid_mechanics/contact/contact_search_explicit.cc @@ -1,633 +1,633 @@ /** * @file contact_search_explicit.cc * @author David Kammer * @date Tue Oct 26 18:49:04 2010 * * @brief Specialization of the contact search structure for 3D within an * explicit time scheme * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "regular_grid_neighbor_structure.hh" #include "contact_search_explicit.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ ContactSearchExplicit::ContactSearchExplicit(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : ContactSearch(contact, neighbors_structure_type, type, id), spatial_dimension(contact.getModel().getSpatialDimension()), mesh(contact.getModel().getFEM().getMesh()) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::findPenetration(const Surface & master_surface, PenetrationList & penetration_list) { AKANTU_DEBUG_IN(); /// get the NodesNeighborList for the given master surface std::map::iterator it_surface; for (it_surface = neighbors_structure.begin(); it_surface != neighbors_structure.end(); ++it_surface) { if(it_surface->first == master_surface) { break; } } AKANTU_DEBUG_ASSERT(it_surface != neighbors_structure.end(), "Master surface not found in this search object " << id); const NodesNeighborList & neighbor_list = dynamic_cast(it_surface->second->getNeighborList()); UInt nb_impactor_nodes = neighbor_list.impactor_nodes.getSize(); Vector * closest_master_nodes = new Vector(nb_impactor_nodes, 1); Vector * has_closest_master_node = new Vector(nb_impactor_nodes, 1, false); findClosestMasterNodes(master_surface, closest_master_nodes, has_closest_master_node); UInt * closest_master_nodes_val = closest_master_nodes->values; bool * has_closest_master_node_val = has_closest_master_node->values; /// get list of impactor and master nodes from neighbor list UInt * impactor_nodes_val = neighbor_list.impactor_nodes.values; //const Mesh & mesh = contact.getModel().getFEM().getMesh(); const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); facet_type[nb_facet_types++] = current_facet_type; /// initialization of penetration list std::stringstream sstr_facets_offset; sstr_facets_offset << id << ":penetrated_facets_offset:" << current_facet_type; - penetration_list.penetrated_facets_offset[current_facet_type] = new Vector(0, 1, sstr_facets_offset.str()); + penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost) = new Vector(0, 1, sstr_facets_offset.str()); std::stringstream sstr_facets; sstr_facets << id << ":penetrated_facets:" << current_facet_type; - penetration_list.penetrated_facets[current_facet_type] = new Vector(0, 1, sstr_facets.str()); + penetration_list.penetrated_facets(current_facet_type, _not_ghost) = new Vector(0, 1, sstr_facets.str()); std::stringstream sstr_normals; sstr_normals << id << ":facets_normals:" << current_facet_type; - penetration_list.facets_normals[current_facet_type] = new Vector(0, spatial_dimension, sstr_normals.str()); + penetration_list.facets_normals(current_facet_type, _not_ghost) = new Vector(0, spatial_dimension, sstr_normals.str()); std::stringstream sstr_gaps; sstr_gaps << id << ":gaps:" << current_facet_type; - penetration_list.gaps[current_facet_type] = new Vector(0, 1, sstr_gaps.str()); + penetration_list.gaps(current_facet_type, _not_ghost) = new Vector(0, 1, sstr_gaps.str()); std::stringstream sstr_projected_positions; sstr_projected_positions << id << ":projected_positions:" << current_facet_type; - penetration_list.projected_positions[current_facet_type] = new Vector(0, spatial_dimension, sstr_projected_positions.str()); + penetration_list.projected_positions(current_facet_type, _not_ghost) = new Vector(0, spatial_dimension, sstr_projected_positions.str()); } } for(UInt in = 0; in < nb_impactor_nodes; ++in) { if (!has_closest_master_node_val[in]) continue; UInt current_impactor_node = impactor_nodes_val[in]; UInt closest_master_node = closest_master_nodes_val[in]; std::vector surface_elements; Vector * are_inside = new Vector(0, 1); Vector * are_in_projection_area = new Vector(0, 1); Element considered_element; for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; - UInt * surface_id_val = mesh.getSurfaceId(type).values; + UInt * surface_id_val = mesh.getSurfaceID(type, _not_ghost).values; - const Vector & node_to_elements_offset = contact.getNodeToElementsOffset(type); - const Vector & node_to_elements = contact.getNodeToElements(type); + const Vector & node_to_elements_offset = contact.getNodeToElementsOffset(type, _not_ghost); + const Vector & node_to_elements = contact.getNodeToElements(type, _not_ghost); UInt * node_to_elements_offset_val = node_to_elements_offset.values; UInt * node_to_elements_val = node_to_elements.values; UInt min_element_offset = node_to_elements_offset_val[closest_master_node]; UInt max_element_offset = node_to_elements_offset_val[closest_master_node + 1]; considered_element.type = type; for(UInt el = min_element_offset; el < max_element_offset; ++el) { UInt surface_element = node_to_elements_val[el]; if(surface_id_val[surface_element] == master_surface) { bool is_inside; bool is_in_projection_area; checkPenetrationSituation(current_impactor_node, surface_element, type, is_inside, is_in_projection_area); considered_element.element = surface_element; surface_elements.push_back(considered_element); are_inside->push_back(is_inside); are_in_projection_area->push_back(is_in_projection_area); } } } UInt nb_penetrated_elements = 0; UInt nb_elements_type[_max_element_type]; memset(nb_elements_type, 0, sizeof(UInt) * _max_element_type); bool * are_inside_val = are_inside->values; bool * are_in_projection_area_val = are_in_projection_area->values; bool is_outside = false; UInt nb_surface_elements = static_cast(surface_elements.size()); // add all elements for which impactor is inside and in projection area for(UInt el = 0; el < nb_surface_elements; ++el) { if(are_inside_val[el] && are_in_projection_area_val[el]) { ElementType current_type = surface_elements.at(el).type; UInt current_element = surface_elements.at(el).element; - penetration_list.penetrated_facets[current_type]->push_back(current_element); + penetration_list.penetrated_facets(current_type, _not_ghost)->push_back(current_element); Real normal[3]; Real projected_position[3]; Real gap; computeComponentsOfProjection(current_impactor_node, current_element, current_type, normal, gap, projected_position); - penetration_list.facets_normals[current_type]->push_back(normal); - penetration_list.projected_positions[current_type]->push_back(projected_position); - penetration_list.gaps[current_type]->push_back(gap); + penetration_list.facets_normals(current_type, _not_ghost)->push_back(normal); + penetration_list.projected_positions(current_type, _not_ghost)->push_back(projected_position); + penetration_list.gaps(current_type, _not_ghost)->push_back(gap); nb_penetrated_elements++; nb_elements_type[current_type]++; } } if(nb_penetrated_elements > 0) { for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { penetration_list.penetrating_nodes.push_back(current_impactor_node); ElementType current_facet_type = mesh.getFacetElementType(type); - penetration_list.penetrated_facets_offset[current_facet_type]->push_back(nb_elements_type[current_facet_type]); + penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost)->push_back(nb_elements_type[current_facet_type]); } } } // if there was no element which is inside and in projection area // check if node is not definitly outside else { for(UInt el = 0; el < nb_surface_elements && !is_outside; ++el) { if(!are_inside_val[el] && are_in_projection_area_val[el]) { is_outside = true; } } // it is not definitly outside take all elements to which it is at least inside if(!is_outside) { bool found_inside_node = false; for(UInt el = 0; el < nb_surface_elements; ++el) { if(are_inside_val[el] && !are_in_projection_area_val[el]) { ElementType current_type = surface_elements.at(el).type; UInt current_element = surface_elements.at(el).element; - penetration_list.penetrated_facets[current_type]->push_back(current_element); + penetration_list.penetrated_facets(current_type, _not_ghost)->push_back(current_element); Real normal[3]; Real projected_position[3]; Real gap; computeComponentsOfProjection(current_impactor_node, current_element, current_type, normal, gap, projected_position); - penetration_list.facets_normals[current_type]->push_back(normal); - penetration_list.projected_positions[current_type]->push_back(projected_position); - penetration_list.gaps[current_type]->push_back(gap); + penetration_list.facets_normals(current_type, _not_ghost)->push_back(normal); + penetration_list.projected_positions(current_type, _not_ghost)->push_back(projected_position); + penetration_list.gaps(current_type, _not_ghost)->push_back(gap); nb_penetrated_elements++; nb_elements_type[current_type]++; found_inside_node = true; } } if(found_inside_node) { for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { penetration_list.penetrating_nodes.push_back(current_impactor_node); ElementType current_facet_type = mesh.getFacetElementType(type); - penetration_list.penetrated_facets_offset[current_facet_type]->push_back(nb_elements_type[current_facet_type]); + penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost)->push_back(nb_elements_type[current_facet_type]); } } } } } delete are_in_projection_area; delete are_inside; } // make the offset table a real offset table for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { ElementType current_facet_type = mesh.getFacetElementType(type); - UInt tmp_nb_facets = penetration_list.penetrated_facets_offset[current_facet_type]->getSize(); - penetration_list.penetrated_facets_offset[current_facet_type]->resize(tmp_nb_facets+1); + UInt tmp_nb_facets = penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost)->getSize(); + penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost)->resize(tmp_nb_facets+1); - Vector & tmp_penetrated_facets_offset = *(penetration_list.penetrated_facets_offset[current_facet_type]); + Vector & tmp_penetrated_facets_offset = *(penetration_list.penetrated_facets_offset(current_facet_type, _not_ghost)); UInt * tmp_penetrated_facets_offset_val = tmp_penetrated_facets_offset.values; for (UInt i = 1; i < tmp_nb_facets; ++i) tmp_penetrated_facets_offset_val[i] += tmp_penetrated_facets_offset_val[i - 1]; for (UInt i = tmp_nb_facets; i > 0; --i) tmp_penetrated_facets_offset_val[i] = tmp_penetrated_facets_offset_val[i - 1]; tmp_penetrated_facets_offset_val[0] = 0; } } delete closest_master_nodes; delete has_closest_master_node; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::findClosestMasterNodes(const Surface & master_surface, Vector * closest_master_nodes, Vector * has_closest_master_node) { AKANTU_DEBUG_IN(); bool * has_closest_master_node_val = has_closest_master_node->values; UInt * closest_master_nodes_val = closest_master_nodes->values; /// get the NodesNeighborList for the given master surface std::map::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { if(it->first == master_surface) { break; } } AKANTU_DEBUG_ASSERT(it != neighbors_structure.end(), "Master surface not found in this search object " << id); const NodesNeighborList & neighbor_list = dynamic_cast(it->second->getNeighborList()); /// get list of impactor and master nodes from neighbor list UInt * impactor_nodes_val = neighbor_list.impactor_nodes.values; UInt * master_nodes_offset_val = neighbor_list.master_nodes_offset.values; UInt * master_nodes_val = neighbor_list.master_nodes.values; /// loop over all impactor nodes and find for each the closest master node UInt nb_impactor_nodes = neighbor_list.impactor_nodes.getSize(); for(UInt imp = 0; imp < nb_impactor_nodes; ++imp) { UInt current_impactor_node = impactor_nodes_val[imp]; UInt min_offset = master_nodes_offset_val[imp]; UInt max_offset = master_nodes_offset_val[imp + 1]; // if there is no master node go to next impactor node if (min_offset == max_offset) continue; Real min_square_distance = std::numeric_limits::max(); UInt closest_master_node = (UInt)-1; // for finding error for(UInt mn = min_offset; mn < max_offset; ++mn) { UInt current_master_node = master_nodes_val[mn]; Real square_distance = computeSquareDistanceBetweenNodes(current_impactor_node, current_master_node); if(min_square_distance > square_distance) { min_square_distance = square_distance; closest_master_node = current_master_node; } } AKANTU_DEBUG_ASSERT(closest_master_node != ((UInt)-1), "could not find a closest master node for impactor node: " << current_impactor_node); has_closest_master_node_val[imp] = true; closest_master_nodes_val[imp] = closest_master_node; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::computeComponentsOfProjection(const UInt impactor_node, const UInt surface_element, const ElementType type, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); switch(type) { case _segment_2: { computeComponentsOfProjectionSegment2(impactor_node, surface_element, normal, gap, projected_position); break; } case _triangle_3: { computeComponentsOfProjectionTriangle3(impactor_node, surface_element, normal, gap, projected_position); break; } case _not_defined: { AKANTU_DEBUG_ERROR("Not a valid surface element type : " << type); break; } case _segment_3: case _triangle_6: case _tetrahedron_4: case _tetrahedron_10: case _quadrangle_4: case _quadrangle_8: case _hexahedron_8: case _point: case _max_element_type: { AKANTU_DEBUG_ERROR("Contact search is not implemented for this surface element type : " << type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::checkPenetrationSituation(const UInt impactor_node, const UInt surface_element, const ElementType type, bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); switch(type) { case _segment_2: { checkPenetrationSituationSegment2(impactor_node, surface_element, is_inside, is_in_projection_area); break; } case _triangle_3: { checkPenetrationSituationTriangle3(impactor_node, surface_element, is_inside, is_in_projection_area); break; } case _not_defined: { AKANTU_DEBUG_ERROR("Not a valid surface element type : " << type); break; } case _segment_3: case _triangle_6: case _tetrahedron_4: case _tetrahedron_10: case _quadrangle_4: case _quadrangle_8: case _hexahedron_8: case _point: case _max_element_type: { AKANTU_DEBUG_ERROR("Contact search is not implemented for this surface element type : " << type); break; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::computeComponentsOfProjectionSegment2(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); const UInt dim = spatial_dimension; const ElementType type = _segment_2; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); Real * current_position = contact.getModel().getCurrentPosition().values; - UInt * connectivity = mesh.getConnectivity(type).values; + UInt * connectivity = mesh.getConnectivity(type, _not_ghost).values; UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_impactor_node = &(current_position[impactor_node * spatial_dimension]); /// compute the normal of the face Real vector_1[2]; Math::vector_2d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! Math::normal2(vector_1, normal); /// compute the gap between impactor and face /// gap positive if impactor outside of surface Real vector_node_1_impactor[2]; Math::vector_2d(position_node_1, position_impactor_node, vector_node_1_impactor); gap = Math::vectorDot2(vector_node_1_impactor, normal); /// compute the projected position of the impactor node onto the face for(UInt i=0; i < dim; ++i) { projected_position[i] = position_impactor_node[i] - gap * normal[i]; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::computeComponentsOfProjectionTriangle3(const UInt impactor_node, const UInt surface_element, Real * normal, Real & gap, Real * projected_position) { AKANTU_DEBUG_IN(); const UInt dim = spatial_dimension; const ElementType type = _triangle_3; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); Real * current_position = contact.getModel().getCurrentPosition().values; - UInt * connectivity = mesh.getConnectivity(type).values; + UInt * connectivity = mesh.getConnectivity(type, _not_ghost).values; UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_node_3 = &(current_position[connectivity[node_1 + 2] * spatial_dimension]); Real * position_impactor_node = &(current_position[impactor_node * spatial_dimension]); /// compute the normal of the face Real vector_1[3]; Real vector_2[3]; Math::vector_3d(position_node_1, position_node_2, vector_1); /// @todo: check if correct order of nodes !! Math::vector_3d(position_node_1, position_node_3, vector_2); Math::normal3(vector_1, vector_2, normal); /// compute the gap between impactor and face /// gap positive if impactor outside of surface Real vector_node_1_impactor[3]; Math::vector_3d(position_node_1, position_impactor_node, vector_node_1_impactor); gap = Math::vectorDot3(vector_node_1_impactor, normal); /// compute the projected position of the impactor node onto the face for(UInt i=0; i < dim; ++i) { projected_position[i] = position_impactor_node[i] - gap * normal[i]; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::checkPenetrationSituationSegment2(const UInt impactor_node, const UInt surface_element, bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(spatial_dimension == 2, "wrong spatial dimension (=" << spatial_dimension << ") for checkPenetrationSituationSegment2"); const ElementType type = _segment_2; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); const Real tolerance = std::numeric_limits::epsilon(); Real * current_position = contact.getModel().getCurrentPosition().values; - UInt * connectivity = mesh.getConnectivity(type).values; + UInt * connectivity = mesh.getConnectivity(type, _not_ghost).values; Real gap; Real normal[2]; Real projected_position[2]; computeComponentsOfProjectionSegment2(impactor_node, surface_element, normal, gap, projected_position); // ------------------------------------------------------- /// Find if impactor node is inside or outside of the face // ------------------------------------------------------- if(gap < -tolerance) is_inside = true; else is_inside = false; // ---------------------------------------------------- /// Find if impactor node is in projection area of face // ---------------------------------------------------- UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real tmp_vector_1_imp[2]; Real tmp_vector_1_2[2]; // find vectors from master node 1 to impactor and master node 2 Math::vector_2d(position_node_1, position_node_2, tmp_vector_1_2); Math::vector_2d(position_node_1, projected_position, tmp_vector_1_imp); Real length_difference = Math::norm2(tmp_vector_1_imp) - Math::norm2(tmp_vector_1_2); // the projection is outside if the test area is larger than the area of the triangle if(length_difference > tolerance) is_in_projection_area = false; else is_in_projection_area = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearchExplicit::checkPenetrationSituationTriangle3(const UInt impactor_node, const UInt surface_element, bool & is_inside, bool & is_in_projection_area) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(spatial_dimension == 3, "wrong spatial dimension (=" << spatial_dimension << ") for checkPenetrationSituationTriangle3"); const ElementType type = _triangle_3; const UInt nb_nodes_element = Mesh::getNbNodesPerElement(type); const Real tolerance = std::numeric_limits::epsilon(); Real * current_position = contact.getModel().getCurrentPosition().values; - UInt * connectivity = mesh.getConnectivity(type).values; + UInt * connectivity = mesh.getConnectivity(type, _not_ghost).values; Real gap; Real normal[3]; Real projected_position[3]; computeComponentsOfProjectionTriangle3(impactor_node, surface_element, normal, gap, projected_position); // ------------------------------------------------------- /// Find if impactor node is inside or outside of the face // ------------------------------------------------------- if(gap < -tolerance) is_inside = true; else is_inside = false; // ---------------------------------------------------- /// Find if impactor node is in projection area of face // ---------------------------------------------------- UInt node_1 = surface_element * nb_nodes_element; Real * position_node_1 = &(current_position[connectivity[node_1 + 0] * spatial_dimension]); Real * position_node_2 = &(current_position[connectivity[node_1 + 1] * spatial_dimension]); Real * position_node_3 = &(current_position[connectivity[node_1 + 2] * spatial_dimension]); Real triangle_area; Real test_area = 0.0; Real tmp_vector_1[3]; Real tmp_vector_2[3]; Real tmp_vector_3[3]; // find area of triangle Math::vector_3d(position_node_1, position_node_2, tmp_vector_1); Math::vector_3d(position_node_1, position_node_3, tmp_vector_2); Math::vectorProduct3(tmp_vector_1, tmp_vector_2, tmp_vector_3); triangle_area = 0.5 * Math::norm3(tmp_vector_3); // compute areas of projected position and two nodes of master triangle UInt nb_sub_areas = nb_nodes_element; UInt node_order[4]; node_order[0] = 0; node_order[1] = 1; node_order[2] = 2; node_order[3] = 0; for(UInt i=0; i < nb_sub_areas; ++i) { position_node_1 = &(current_position[connectivity[node_1 + node_order[i ]] * spatial_dimension]); position_node_2 = &(current_position[connectivity[node_1 + node_order[i+1]] * spatial_dimension]); Math::vector_3d(projected_position, position_node_1, tmp_vector_1); Math::vector_3d(projected_position, position_node_2, tmp_vector_2); Math::vectorProduct3(tmp_vector_1, tmp_vector_2, tmp_vector_3); test_area += 0.5 * Math::norm3(tmp_vector_3); } // the projection is outside if the test area is larger than the area of the triangle if((test_area - triangle_area) > tolerance) is_in_projection_area = false; else is_in_projection_area = true; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc b/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc index e9fb51375..a53e68ffc 100644 --- a/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc +++ b/model/solid_mechanics/contact/grid_2d_neighbor_structure.cc @@ -1,624 +1,624 @@ /** * @file grid_2d_neighbor_structure.cc * @author Leonardo Snozzi * @date Tue Dec 7 13:04:58 2010 * - * @brief + * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_search.hh" #include "solid_mechanics_model.hh" #include "grid_2d_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ Grid2dNeighborStructure::Grid2dNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, - const ContactNeighborStructureID & id) : - ContactNeighborStructure(contact_search, master_surface, type, id), + const ContactNeighborStructureID & id) : + ContactNeighborStructure(contact_search, master_surface, type, id), mesh(contact_search.getContact().getModel().getFEM().getMesh()) { AKANTU_DEBUG_IN(); UInt spatial_dimension = contact_search.getContact().getModel().getFEM().getMesh().getSpatialDimension(); if(spatial_dimension != 2) AKANTU_DEBUG_ERROR("Wrong ContactType for contact in 2d!"); /// make sure that the increments are computed const_cast(contact_search.getContact().getModel()).setIncrementFlagOn(); /// set increment to zero max_increment[0] = 0.; max_increment[1] = 0.; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Grid2dNeighborStructure::~Grid2dNeighborStructure() { AKANTU_DEBUG_IN(); delete neighbor_list; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::initNeighborStructure() { AKANTU_DEBUG_IN(); neighbor_list = new NeighborList(); createGrid(true); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool Grid2dNeighborStructure::check() { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); Real * inc_val = contact_search.getContact().getModel().getIncrement().values; Real max[2] = {0. ,0.}; UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; for (UInt s = 0; s < nb_surfaces; ++s) for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[n+1]; ++n) { UInt i_node = surf_nodes[n]; - for (UInt i = 0; i < 2; ++i) + for (UInt i = 0; i < 2; ++i) max[i] = std::max(max[i], fabs(inc_val[2*i_node+i])); } for (UInt i = 0; i < 2; ++i) { max_increment[i] += max[i]; if(max_increment[i] > spacing) - return true; + return true; } return false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::update() { AKANTU_DEBUG_IN(); delete[] this->neighbor_list; neighbor_list = new NeighborList(); createGrid(false); - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::createGrid(bool initial_position) { AKANTU_DEBUG_IN(); Real * coord; if (initial_position) coord = mesh.getNodes().values; else coord = contact_search.getContact().getModel().getCurrentPosition().values; UInt nb_surfaces = mesh.getNbSurfaces(); - + /// get the size of the grid spacing = getMinSize(coord); /// get bounds of master surface Real * x_bounds = new Real[2*nb_surfaces]; Real * y_bounds = new Real[2*nb_surfaces]; getBounds(coord, x_bounds, y_bounds); - + /// find intersections between mastersurface and the other ones Real x_intersection[2]; Real y_intersection[2]; bool intersection = getBoundsIntersection(x_bounds, y_bounds, x_intersection, y_intersection); /// if every slave surfaces to far away from master surface neighbor list is empty if(intersection == false) return; /// adjust intersection space x_intersection[0] -= 1.49999*spacing; x_intersection[1] += 1.49999*spacing; y_intersection[0] -= 1.49999*spacing; y_intersection[1] += 1.49999*spacing; x_intersection[0] = std::max(x_intersection[0], x_bounds[2*master_surface]); x_intersection[1] = std::min(x_intersection[0+1], x_bounds[2*master_surface+1]); y_intersection[0] = std::max(y_intersection[0], y_bounds[2*master_surface]); y_intersection[1] = std::min(y_intersection[0+1], y_bounds[2*master_surface+1]); /// define grid dimension UInt nb_cells[3]; nb_cells[0] = std::ceil(fabs(x_intersection[1]-x_intersection[0])/spacing); nb_cells[1] = std::ceil(fabs(y_intersection[1]-y_intersection[0])/spacing); nb_cells[2] = nb_cells[0]*nb_cells[1]; Real origin[2]; origin[0] = x_intersection[0] - (nb_cells[0]*spacing-fabs(x_intersection[1]-x_intersection[0]))/2.; origin[1] = y_intersection[0] - (nb_cells[1]*spacing-fabs(y_intersection[1]-y_intersection[0]))/2.; /// fill grid cells with master segments Vector cell_to_segments(0, 1); UInt * cell_to_segments_offset = new UInt[nb_cells[2]+1]; memset(cell_to_segments_offset, 0, (nb_cells[2]+1)*sizeof(UInt)); traceSegments(coord, origin, nb_cells, cell_to_segments_offset, cell_to_segments); /// loop over slave nodes to find out impactor ones UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt * impactors = neighbor_list->impactor_nodes.values; UInt * cell_seg_val = cell_to_segments.values; ElementType el_type = _segment_2; /* Only linear element at the moment */ - UInt * conn_val = contact_search.getContact().getModel().getFEM().getMesh().getConnectivity(el_type).values; + UInt * conn_val = contact_search.getContact().getModel().getFEM().getMesh().getConnectivity(el_type, _not_ghost).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); std::stringstream sstr_fo; sstr_fo << id << ":facets_offset:" << el_type; - neighbor_list->facets_offset[el_type] = new Vector(0, 1, sstr_fo.str()); + neighbor_list->facets_offset(el_type, _not_ghost) = new Vector(0, 1, sstr_fo.str()); std::stringstream sstr_f; sstr_f << id << ":facets:" << el_type; - neighbor_list->facets[el_type] = new Vector(0, 1, sstr_f.str()); - neighbor_list->facets_offset[el_type]->push_back((UInt)0); + neighbor_list->facets(el_type, _not_ghost) = new Vector(0, 1, sstr_f.str()); + neighbor_list->facets_offset(el_type, _not_ghost)->push_back((UInt)0); const Int cell_index[9][2] = {{0,-1},{-1,-1},{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1}}; Int nb_x = nb_cells[0]; Int nb_y = nb_cells[1]; Vector checked(0,1); /// loop over slave surfaces for (UInt s = 0; s < nb_surfaces; ++s) { if(s == master_surface) continue; /// check is slave surface inside grid if(x_bounds[2*s+1] < origin[0] || y_bounds[2*s+1] < origin[1]) continue; if(x_bounds[2*s] > origin[0]+spacing*nb_cells[0] || y_bounds[2*s] > origin[1]+spacing*nb_cells[1]) continue; /// loop over slave nodes of considered surface for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[s+1]; ++n) { UInt i_node = surf_nodes[n]; Real x_node = (coord[2*i_node] - origin[0])/spacing; Real y_node = (coord[2*i_node+1] - origin[1])/spacing; - + Int ii = (int)(x_node); Int jj = (int)(y_node); /// is node in one grid cell? if((ii < 0 || jj < 0) || (ii>=nb_x || jj>=nb_y)) continue; Int i_start; /* which cells are to be considered */ if(std::ceil(x_node-ii-0.5)==1 && std::ceil(y_node-jj-0.5)==0) i_start = 3; else { i_start = std::ceil(x_node-ii-0.5) + std::ceil(y_node-jj-0.5); } checked.empty(); bool stored = false; /// look at actual cell and 3 adjacent cells for (Int k = -1; k < 3; ++k) { - + Int x_index = ii; Int y_index = jj; if ( k >= 0) { x_index += cell_index[i_start*2+k][0]; y_index += cell_index[i_start*2+k][1]; if ((x_index < 0 || y_index < 0) || (x_index>=nb_x || y_index>=nb_y)) continue; /* cell does not exists */ } UInt i_cell = (UInt)(x_index+y_index*nb_x); - + /// loop over segments related to the considered cell for (UInt el = cell_to_segments_offset[i_cell]; el < cell_to_segments_offset[i_cell+1]; ++el) { UInt i_segment = cell_seg_val[el]; bool i_checked = false; for (UInt l=0; l1.) { Real dist; if(proj < 0.) dist = Math::distance_2d(x1, x3); else dist = Math::distance_2d(x2, x3); if(dist < 0.5*spacing) { if (stored == false) { stored = true; neighbor_list->impactor_nodes.push_back(i_node); - neighbor_list->facets_offset[el_type]->push_back((UInt)0); + neighbor_list->facets_offset(el_type, _not_ghost)->push_back((UInt)0); } - neighbor_list->facets_offset[el_type]->values[neighbor_list->impactor_nodes.getSize()]++; - neighbor_list->facets[el_type]->push_back(i_segment); + neighbor_list->facets_offset(el_type, _not_ghost)->values[neighbor_list->impactor_nodes.getSize()]++; + neighbor_list->facets(el_type, _not_ghost)->push_back(i_segment); } } else { Real vec_normal[2]; Math::normal2(vec_surf, vec_normal); Real gap = Math::vectorDot2(vec_dist, vec_normal); if(fabs(gap) < 0.5*spacing) { if (stored == false) { stored = true; neighbor_list->impactor_nodes.push_back(i_node); - neighbor_list->facets_offset[el_type]->push_back((UInt)0); + neighbor_list->facets_offset(el_type, _not_ghost)->push_back((UInt)0); } - neighbor_list->facets_offset[el_type]->values[neighbor_list->impactor_nodes.getSize()]++; - neighbor_list->facets[el_type]->push_back(i_segment); + neighbor_list->facets_offset(el_type, _not_ghost)->values[neighbor_list->impactor_nodes.getSize()]++; + neighbor_list->facets(el_type, _not_ghost)->push_back(i_segment); } } } } /* end loop segments */ } /* end loop over cells */ - + } /* end loop over slave nodes */ } /* end loop over surfaces */ /// convert occurence array in a csv one - UInt * facet_off = neighbor_list->facets_offset[el_type]->values; - for (UInt i = 1; i < neighbor_list->facets_offset[el_type]->getSize(); ++i) facet_off[i] += facet_off[i-1]; - + UInt * facet_off = neighbor_list->facets_offset(el_type, _not_ghost)->values; + for (UInt i = 1; i < neighbor_list->facets_offset(el_type, _not_ghost)->getSize(); ++i) facet_off[i] += facet_off[i-1]; + /// free temporary vectors delete[] x_bounds; delete[] y_bounds; delete[] cell_to_segments_offset; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Grid2dNeighborStructure::getMinSize(Real * coord) { AKANTU_DEBUG_IN(); ElementType el_type = _segment_2; /* Only linear element at the moment */ - UInt * conn_val = mesh.getConnectivity(el_type).values; - - UInt nb_elements = mesh.getConnectivity(el_type).getSize(); - UInt * surface_id_val = mesh.getSurfaceId(el_type).values; + UInt * conn_val = mesh.getConnectivity(el_type, _not_ghost).values; + + UInt nb_elements = mesh.getConnectivity(el_type, _not_ghost).getSize(); + UInt * surface_id_val = mesh.getSurfaceID(el_type, _not_ghost).values; UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); Real min_size = std::numeric_limits::max(); /// loop over master segments for (UInt el = 0; el < nb_elements; ++el) if (surface_id_val[el] == master_surface) { Real * x1 = &coord[2*conn_val[el*elem_nodes]]; Real * x2 = &coord[2*conn_val[el*elem_nodes+1]]; Real length = (x1[0]-x2[0])*(x1[0]-x2[0])+(x1[1]-x2[1])*(x1[1]-x2[1]); if (length < min_size) - min_size = length; + min_size = length; } return sqrt(min_size); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Grid2dNeighborStructure::getBounds(Real * coord, Real * x_bounds, Real * y_bounds) { AKANTU_DEBUG_IN(); /// initialize bounds UInt nb_surfaces = mesh.getNbSurfaces(); for (UInt s = 0; s < nb_surfaces; ++s) { x_bounds[s*2] = std::numeric_limits::max(); x_bounds[s*2+1] = -std::numeric_limits::max(); y_bounds[s*2] = std::numeric_limits::max(); y_bounds[s*2+1] = -std::numeric_limits::max(); } UInt * surf_nodes_off = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surf_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find min and max coordinates of each surface for (UInt s = 0; s < nb_surfaces; ++s) { for (UInt n = surf_nodes_off[s]; n < surf_nodes_off[s+1]; ++n) { UInt i_node = surf_nodes[n]; if(coord[i_node*2] < x_bounds[s*2]) x_bounds[s*2] = coord[i_node*2]; - + if(coord[i_node*2] > x_bounds[2*s+1]) x_bounds[2*s+1] = coord[i_node*2]; - + if(coord[i_node*2+1] < y_bounds[2*s]) y_bounds[2*s] = coord[i_node*2+1]; if(coord[i_node*2+1] > y_bounds[2*s+1]) y_bounds[2*s+1] = coord[i_node*2+1]; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool Grid2dNeighborStructure::getBoundsIntersection(Real * x_bounds, Real * y_bounds, Real * x_int, Real * y_int) { AKANTU_DEBUG_IN(); bool find_intersection = false; UInt nb_surfaces = mesh.getNbSurfaces(); x_int[0] = std::numeric_limits::max(); x_int[1] = -std::numeric_limits::max(); y_int[0] = std::numeric_limits::max(); y_int[1] = -std::numeric_limits::max(); /// enlarge bounds of master surface within a tolerance x_bounds[2*master_surface] -= 1.49999*spacing; x_bounds[2*master_surface+1] += 1.49999*spacing; y_bounds[2*master_surface] -= 1.49999*spacing; y_bounds[2*master_surface+1] += 1.49999*spacing; /// loop over surfaces for (UInt s = 0; s < nb_surfaces; ++s) { if(s == master_surface) continue; Real x_temp[2] = {REAL_INIT_VALUE, REAL_INIT_VALUE}; Real y_temp[2] = {REAL_INIT_VALUE, REAL_INIT_VALUE}; /// find if intersection in x exists if(x_bounds[2*master_surface] > x_bounds[2*s]) { /* starting point of possible intersection */ x_temp[0] = x_bounds[2*master_surface]; /* find ending point of possible intersection */ if(x_bounds[2*s+1] < x_bounds[2*master_surface]) continue; else if(x_bounds[2*s+1] < x_bounds[2*master_surface+1]) x_temp[1] = x_bounds[2*s+1]; else x_temp[1] = x_bounds[2*master_surface+1]; } else { /* starting point of possible intersection */ x_temp[0] = x_bounds[2*s]; /* find ending point of possible intersection */ if(x_bounds[2*master_surface+1] < x_bounds[2*s]) continue; else if(x_bounds[2*master_surface+1] < x_bounds[2*s+1]) x_temp[1] = x_bounds[2*master_surface+1]; else x_temp[1] = x_bounds[2*s+1]; } /// find if intersection in y exists if(y_bounds[2*master_surface] > y_bounds[2*s]) { /* starting point of possible intersection */ y_temp[0] = y_bounds[2*master_surface]; /* find ending point of possible intersection */ if(y_bounds[2*s+1] < y_bounds[2*master_surface]) continue; else if(y_bounds[2*s+1] < y_bounds[2*master_surface+1]) y_temp[1] = y_bounds[2*s+1]; else y_temp[1] = y_bounds[2*master_surface+1]; } else { /* starting point of possible intersection */ y_temp[0] = y_bounds[2*s]; /* find ending point of possible intersection */ if(y_bounds[2*master_surface+1] < y_bounds[2*s]) continue; else if(y_bounds[2*master_surface+1] < y_bounds[2*s+1]) y_temp[1] = y_bounds[2*master_surface+1]; else y_temp[1] = y_bounds[2*s+1]; } /// intersection exists, find its minimum/maximum find_intersection = true; x_int[0] = std::min(x_int[0], x_temp[0]); x_int[1] = std::max(x_int[1], x_temp[1]); y_int[0] = std::min(y_int[0], y_temp[0]); y_int[1] = std::max(y_int[1], y_temp[1]); } return find_intersection; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Grid2dNeighborStructure::traceSegments(Real * coord, Real * origin, +void Grid2dNeighborStructure::traceSegments(Real * coord, Real * origin, UInt * nb_cells, UInt * cell_to_seg_off, Vector & cell_to_segments) { AKANTU_DEBUG_IN(); Vector temp(0, 2); UInt index[2] = {0, 0}; ElementType el_type = _segment_2; /* Only linear element at the moment */ UInt elem_nodes = Mesh::getNbNodesPerElement(el_type); - UInt * surface_id_val = mesh.getSurfaceId(el_type).values; - UInt * conn_val = mesh.getConnectivity(el_type).values; - UInt nb_segments = mesh.getConnectivity(el_type).getSize(); + UInt * surface_id_val = mesh.getSurfaceID(el_type, _not_ghost).values; + UInt * conn_val = mesh.getConnectivity(el_type, _not_ghost).values; + UInt nb_segments = mesh.getConnectivity(el_type, _not_ghost).getSize(); Int nb_x = nb_cells[0]; Int nb_y = nb_cells[1]; /// Detect cells which are crossed by the segments for (UInt el = 0; el < nb_segments; ++el) if (surface_id_val[el] == master_surface) { /* Compute relative coords and index of the staring and ending cell (in respect to the grid) */ Real x1 = (coord[2*conn_val[elem_nodes*el]] - origin[0])/spacing; Real y1 = (coord[2*conn_val[elem_nodes*el]+1] - origin[1])/spacing; Real x2 = (coord[2*conn_val[elem_nodes*el+1]] - origin[0])/spacing; Real y2 = (coord[2*conn_val[elem_nodes*el+1]+1] - origin[1])/spacing; Int ii = (Int)std::floor(x1); Int jj = (Int)std::floor(y1); Int kk = (Int)std::floor(x2); Int ll = (Int)std::floor(y2); /// check if segment outside grid if((std::max(ii,kk)<0 || std::min(ii,kk)>=nb_x) || (std::max(jj,ll)<0 || std::min(jj,ll)>=nb_y)) continue; /* */ Real dx = fabs(x2-x1); Real dy = fabs(y2-y1); Int n = 0; Int ii_inc, jj_inc; Real error; if(dx == 0.) { ii_inc = 0; error = std::numeric_limits::max(); } else if(x2 > x1) { ii_inc = 1; n = kk-ii; error = (ii+1-x1)*dy; } else { /* x1 < x2 */ ii_inc = -1; n = ii-kk; error = (x1-ii)*dy; } if(dy == 0.) { jj_inc = 0; error = -std::numeric_limits::max(); } else if(y2 > y1) { jj_inc = 1; n += ll-jj; error -= (jj+1-y1)*dx; } else { /* y1 < y2 */ jj_inc = -1; n += jj-ll; error -= (y1-jj)*dx; } while(true) { /* check if intersected cell belong to the grid */ if((ii>=0 && ii< nb_x) && (jj>=0 && jj 0) { /* ..move in y-direction */ jj += jj_inc; error -= dx; } else { /* ..move in x-direction */ ii += ii_inc; error += dy; } n--; } } /// convert the occurrence array in a csr one for (UInt i = 1; i < nb_cells[2]; ++i) cell_to_seg_off[i] += cell_to_seg_off[i-1]; for (UInt i = nb_cells[2]; i > 0; --i) cell_to_seg_off[i] = cell_to_seg_off[i-1]; cell_to_seg_off[0] = 0; /// rearrange segments to get the cell-segments list cell_to_segments.resize(cell_to_seg_off[nb_cells[2]]); UInt * cell_val = cell_to_segments.values; UInt * tmp = temp.values; UInt nb_traced = temp.getSize(); for (UInt i = 0; i < nb_traced; i++) { cell_val[cell_to_seg_off[tmp[2*i]]] = tmp[2*i+1]; cell_to_seg_off[tmp[2*i]]++; } /// reconvert occurence array in a csr one for (UInt i = nb_cells[2]; i > 0; --i) cell_to_seg_off[i] = cell_to_seg_off[i-1]; cell_to_seg_off[0] = 0; AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc b/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc index 54c6017ec..0a1244126 100644 --- a/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc +++ b/model/solid_mechanics/contact/regular_grid_neighbor_structure.cc @@ -1,758 +1,758 @@ /** * @file regular_grid_neighbor_structure.cc * @author David Kammer * @date Mon Oct 11 16:03:17 2010 * * @brief Specialization of the contact neighbor structure for regular grid * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_rigid.hh" #include "solid_mechanics_model.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ -NodesNeighborList::NodesNeighborList() : NeighborList(), +NodesNeighborList::NodesNeighborList() : NeighborList(), master_nodes_offset(Vector(0, 1, "master_nodes_offset")), master_nodes (Vector(0, 1, "master_nodes")) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template +template RegularGridNeighborStructure::RegularGridNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id) : ContactNeighborStructure(contact_search, master_surface, type, id), mesh(contact_search.getContact().getModel().getFEM().getMesh()) { - + AKANTU_DEBUG_IN(); /// chose the neighbor list and initialize it /*if (contact_search.getType() == _cst_3d_expli) { neighbor_list = new NodesNeighborList(); nodes_neighbor_list = true; } else { neighbor_list = new NeighborList(); nodes_neighbor_list = false; } */ this->constructNeighborList(); /// make sure that the increments are computed const_cast(contact_search.getContact().getModel()).setIncrementFlagOn(); /// arbitrary initial value grid_spacing[0] = 0.05; grid_spacing[1] = 0.05; grid_spacing[2] = 0.05; - /// securty factor of max 0.5 is needed for a neighborlist that is always complete + /// securty factor of max 0.5 is needed for a neighborlist that is always complete security_factor[0] = 0.5; security_factor[1] = 0.5; security_factor[2] = 0.5; /// maximal increment since last update of neighborlist max_increment[0] = 0.0; max_increment[1] = 0.0; max_increment[2] = 0.0; - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template RegularGridNeighborStructure::~RegularGridNeighborStructure() { AKANTU_DEBUG_IN(); delete neighbor_list; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template +template void RegularGridNeighborStructure::initNeighborStructure() { AKANTU_DEBUG_IN(); - this->setMinimalGridSpacing(); + this->setMinimalGridSpacing(); //Real * node_coordinates = mesh.getNodes().values; Real * node_coordinates = contact_search.getContact().getModel().getCurrentPosition().values; this->update(node_coordinates); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template +template void RegularGridNeighborStructure::update() { AKANTU_DEBUG_IN(); this->setMinimalGridSpacing(); // delete neighbor list and reconstruct it delete this->neighbor_list; this->constructNeighborList(); Real * node_current_position = contact_search.getContact().getModel().getCurrentPosition().values; this->update(node_current_position); /// reset max_increment to zero for(UInt i = 0; i < spatial_dimension; ++i) max_increment[i] = 0.0; - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template +template void RegularGridNeighborStructure::update(Real * node_position) { AKANTU_DEBUG_IN(); UInt nb_surfaces = mesh.getNbSurfaces(); - AKANTU_DEBUG_ASSERT(master_surface < nb_surfaces, "Master surface (" << - master_surface << ") out of surface range (number of surfaces: " << + AKANTU_DEBUG_ASSERT(master_surface < nb_surfaces, "Master surface (" << + master_surface << ") out of surface range (number of surfaces: " << nb_surfaces << ") !!"); // ---------------------------- /// find max and min values for each surface // ---------------------------- Real bound_max[nb_surfaces][spatial_dimension]; Real bound_min[nb_surfaces][spatial_dimension]; /// initialize max and min table with extrem values for(UInt surf = 0; surf < nb_surfaces; ++surf) { for(UInt dim = 0; dim < spatial_dimension; ++dim) { bound_max[surf][dim] = - std::numeric_limits::max(); bound_min[surf][dim] = std::numeric_limits::max(); } } // get nodes that are on a given surface UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find max and min values of current position for each surface for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_position[cur_node * spatial_dimension + dim]; bound_max[surf][dim] = std::max(bound_max[surf][dim], cur_position); bound_min[surf][dim] = std::min(bound_min[surf][dim], cur_position); } - } + } } // ---------------------------- /// define grid geometry // ---------------------------- /// define grid geometry around the master surface Real grid_min[spatial_dimension]; Real grid_max[spatial_dimension]; Int directional_nb_cells[spatial_dimension]; UInt nb_cells = 1; - + for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real grid_length = bound_max[master_surface][dim] - bound_min[master_surface][dim]; /// get nb of cells needed to cover total length and add a cell to each side (start, end) directional_nb_cells[dim] = static_cast(ceil(grid_length / grid_spacing[dim])) + 2; nb_cells *= directional_nb_cells[dim]; Real additional_grid_length = (directional_nb_cells[dim]*grid_spacing[dim] - grid_length) / 2.; /// get minimal and maximal coordinates of the grid grid_min[dim] = bound_min[master_surface][dim] - additional_grid_length; grid_max[dim] = bound_max[master_surface][dim] + additional_grid_length; } // ---------------------------- /// find surfaces being in the grid space // ---------------------------- - AKANTU_DEBUG_ASSERT(contact_search.getContact().getType() == _ct_rigid, - "This contact type (" << contact_search.getContact().getType() << + AKANTU_DEBUG_ASSERT(contact_search.getContact().getType() == _ct_rigid, + "This contact type (" << contact_search.getContact().getType() << ") does not work with this neighbor structure"); // find impactor_surfaces for given master const ContactRigid & its_contact = dynamic_cast(contact_search.getContact()); const ContactRigid::SurfaceToImpactInfoMap & imp_info = its_contact.getImpactorsInformation(); ContactRigid::SurfaceToImpactInfoMap::const_iterator it; it = imp_info.find(this->master_surface); - AKANTU_DEBUG_ASSERT(it != imp_info.end(), + AKANTU_DEBUG_ASSERT(it != imp_info.end(), "Could not find impactor surfaces for master surface " << master_surface); std::vector * impactor_surfaces = it->second->impactor_surfaces; /* const std::vector imp_info = its_contact.getImpactorsInformation(); std::vector * impactor_surfaces = NULL; for (UInt m=0; m < imp_info.size(); ++m) { ContactRigid::ImpactorInformationPerMaster * impactor_info = imp_info.at(m); if (impactor_info->master_id == this->master_surface) { impactor_surfaces = impactor_info->impactor_surfaces; break; } } - AKANTU_DEBUG_ASSERT(impactor_surfaces != NULL, + AKANTU_DEBUG_ASSERT(impactor_surfaces != NULL, "Could not find impactor surfaces for master surface " << master_surface); */ /// find surfaces being in the grid space UInt nb_grid_surfaces = 0; UInt grid_surfaces[nb_surfaces]; bool not_grid_space = false; for(UInt s = 0; s < impactor_surfaces->size(); ++s) { UInt surf = impactor_surfaces->at(s); for(UInt dim = 0; dim < spatial_dimension; ++dim) { if(bound_max[surf][dim] < grid_min[dim] || bound_min[surf][dim] > grid_max[dim]) not_grid_space = true; } if(!not_grid_space) { grid_surfaces[nb_grid_surfaces++] = surf; } not_grid_space = false; } grid_surfaces[nb_grid_surfaces++] = this->master_surface; /// if number of grid surfaces is equal to 1 we do not need to consider any slave surface /// @todo exit with empty neighbor list // ---------------------------- /// define cell number for all surface nodes // ---------------------------- /// assign cell number to all surface nodes (put -1 if out of grid space) (cell numbers start with zero) Int not_grid_space_node = -1; // should not be same as not_grid_space_surface and be < 0 Int not_grid_space_surface = -2; // should not be same as not_grid_space_node and be < 0 Int directional_cell[spatial_dimension]; UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Vector * cell = new Vector(nb_surface_nodes, 1, not_grid_space_surface); Int * cell_val = cell->values; /// define the cell number for all surface nodes for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; /// compute cell index for all directions for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_position[cur_node * spatial_dimension + dim]; directional_cell[dim] = static_cast(floor((cur_position - grid_min[dim])/grid_spacing[dim])); } - + /// test if out of grid space for(UInt dim = 0; dim < spatial_dimension; ++dim) { if(directional_cell[dim] < 0 || directional_cell[dim] >= directional_nb_cells[dim]) { cell_val[n] = not_grid_space_node; } } - + /// compute global cell index if(cell_val[n] != not_grid_space_node) cell_val[n] = computeCellNb(directional_nb_cells, directional_cell); } - } + } // ---------------------------- /// find all impactor and master nodes for given cell // ---------------------------- /// define offset arrays for nodes per cell which will be computed below UInt * impactor_nodes_cell_offset = new UInt[nb_cells + 1]; memset(impactor_nodes_cell_offset, 0, nb_cells * sizeof(UInt)); UInt * master_nodes_cell_offset = new UInt[nb_cells + 1]; memset(master_nodes_cell_offset, 0, nb_cells * sizeof(UInt)); - + /// count number of nodes per cell for impactors and master for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; /// define temporary pointers UInt * nodes_cell_offset; if(current_surface == master_surface) { nodes_cell_offset = master_nodes_cell_offset; } else { nodes_cell_offset = impactor_nodes_cell_offset; } for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { Int cur_cell = cell_val[n]; if(cur_cell != not_grid_space_node) nodes_cell_offset[cur_cell]++; } } /// create two separate offset arrays for impactor nodes and master nodes for (UInt i = 1; i < nb_cells; ++i) { impactor_nodes_cell_offset[i] += impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] += master_nodes_cell_offset [i - 1]; } for (UInt i = nb_cells; i > 0; --i) { impactor_nodes_cell_offset[i] = impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] = master_nodes_cell_offset [i - 1]; } impactor_nodes_cell_offset[0] = 0; master_nodes_cell_offset [0] = 0; /// find all impactor and master nodes in a cell UInt * impactor_nodes_cell = new UInt[impactor_nodes_cell_offset[nb_cells]]; UInt * master_nodes_cell = new UInt[master_nodes_cell_offset [nb_cells]]; cell_val = cell->values; for(UInt surf = 0; surf < nb_grid_surfaces; ++surf) { UInt current_surface = grid_surfaces[surf]; UInt min_surf_offset = surface_to_nodes_offset[current_surface]; UInt max_surf_offset = surface_to_nodes_offset[current_surface + 1]; /// define temporary variables UInt * nodes_cell; UInt * nodes_cell_offset; if(current_surface == master_surface) { nodes_cell = master_nodes_cell; nodes_cell_offset = master_nodes_cell_offset; } else { nodes_cell = impactor_nodes_cell; nodes_cell_offset = impactor_nodes_cell_offset; } /// loop over the nodes of surf and create nodes_cell for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt node = surface_to_nodes[n]; Int cur_cell = cell_val[n]; if(cur_cell != not_grid_space_node) nodes_cell[nodes_cell_offset[cur_cell]++] = node; } } for (UInt i = nb_cells; i > 0; --i) { impactor_nodes_cell_offset[i] = impactor_nodes_cell_offset[i - 1]; master_nodes_cell_offset [i] = master_nodes_cell_offset[i - 1]; } impactor_nodes_cell_offset[0] = 0; master_nodes_cell_offset [0] = 0; - + if(nodes_neighbor_list == true) - constructNodesNeighborList(directional_nb_cells, - nb_cells, - cell, - impactor_nodes_cell_offset, - impactor_nodes_cell, - master_nodes_cell_offset, + constructNodesNeighborList(directional_nb_cells, + nb_cells, + cell, + impactor_nodes_cell_offset, + impactor_nodes_cell, + master_nodes_cell_offset, master_nodes_cell); else - constructNeighborList(directional_nb_cells, - nb_cells, - cell, - impactor_nodes_cell_offset, - impactor_nodes_cell, - master_nodes_cell_offset, + constructNeighborList(directional_nb_cells, + nb_cells, + cell, + impactor_nodes_cell_offset, + impactor_nodes_cell, + master_nodes_cell_offset, master_nodes_cell); - + delete [] impactor_nodes_cell; delete [] impactor_nodes_cell_offset; delete [] master_nodes_cell; delete [] master_nodes_cell_offset; delete cell; - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template -void RegularGridNeighborStructure::constructNeighborList(Int directional_nb_cells[spatial_dimension], - UInt nb_cells, - Vector * cell, - UInt * impactor_nodes_cell_offset, - UInt * impactor_nodes_cell, - UInt * master_nodes_cell_offset, +template +void RegularGridNeighborStructure::constructNeighborList(Int directional_nb_cells[spatial_dimension], + UInt nb_cells, + Vector * cell, + UInt * impactor_nodes_cell_offset, + UInt * impactor_nodes_cell, + UInt * master_nodes_cell_offset, UInt * master_nodes_cell) { AKANTU_DEBUG_IN(); UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Int * cell_val = cell->values; UInt nb_impactor_nodes = impactor_nodes_cell_offset[nb_cells]; //neighbor_list->impactor_nodes.resize(nb_impactor_nodes); //UInt * impactor_nodes_val = neighbor_list->impactor_nodes.values; /// define maximal number of neighbor cells and include it-self UInt max_nb_neighbor_cells; if(spatial_dimension == 2) { max_nb_neighbor_cells = 9; } else if(spatial_dimension == 3) { max_nb_neighbor_cells = 27; } const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; - + for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { facet_type[nb_facet_types++] = mesh.getFacetElementType(type); } } /// loop over all existing surface element types for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; - const Vector & node_to_elements_offset = contact_search.getContact().getNodeToElementsOffset(type); - const Vector & node_to_elements = contact_search.getContact().getNodeToElements(type); + const Vector & node_to_elements_offset = contact_search.getContact().getNodeToElementsOffset(type, _not_ghost); + const Vector & node_to_elements = contact_search.getContact().getNodeToElements(type, _not_ghost); UInt * node_to_elements_offset_val = node_to_elements_offset.values; UInt * node_to_elements_val = node_to_elements.values; - UInt * surface_id_val = mesh.getSurfaceId(type).values; + UInt * surface_id_val = mesh.getSurfaceID(type, _not_ghost).values; Vector * visited_node = new Vector(nb_impactor_nodes, 1, false); // does it need a delete at the end ? bool * visited_node_val = visited_node->values; UInt neighbor_cells[max_nb_neighbor_cells]; - - std::stringstream sstr_name_offset; + + std::stringstream sstr_name_offset; sstr_name_offset << id << ":facets_offset:" << type; - neighbor_list->facets_offset[type] = new Vector(0, 1, sstr_name_offset.str()); - Vector & tmp_facets_offset = *(neighbor_list->facets_offset[type]); + neighbor_list->facets_offset(type, _not_ghost) = new Vector(0, 1, sstr_name_offset.str()); + Vector & tmp_facets_offset = *(neighbor_list->facets_offset(type, _not_ghost)); std::stringstream sstr_name; sstr_name << id << ":facets:" << type; - neighbor_list->facets[type] = new Vector(0, 1, sstr_name.str());// declare vector that is ?? - Vector & tmp_facets = *(neighbor_list->facets[type]); + neighbor_list->facets(type, _not_ghost) = new Vector(0, 1, sstr_name.str());// declare vector that is ?? + Vector & tmp_facets = *(neighbor_list->facets(type, _not_ghost)); for(UInt in = 0; in < nb_impactor_nodes; ++in) { UInt current_impactor_node = impactor_nodes_cell[in]; /// test if nodes has not already been visited if(!visited_node_val[in]) { - + /// find and store cell numbers of neighbor cells and it-self Int tmp_cell = - std::numeric_limits::max();; bool init = false; for(UInt i = 0; i < nb_surface_nodes; ++i) { if(surface_to_nodes[i] == current_impactor_node) { tmp_cell = std::max(tmp_cell, cell_val[i]); init = true; } } - AKANTU_DEBUG_ASSERT(init, "Cell number of node is not initialized"); - AKANTU_DEBUG_ASSERT(tmp_cell >= 0, "Bad cell index. Found cell nb of impactor = " << tmp_cell << " This case normally should not happen!"); + AKANTU_DEBUG_ASSERT(init, "Cell number of node is not initialized"); + AKANTU_DEBUG_ASSERT(tmp_cell >= 0, "Bad cell index. Found cell nb of impactor = " << tmp_cell << " This case normally should not happen!"); UInt current_cell = tmp_cell; - + //UInt current_cell = cell_val[current_impactor_node]; UInt nb_neighbor_cells = computeNeighborCells(current_cell, neighbor_cells, directional_nb_cells); neighbor_cells[nb_neighbor_cells++] = current_cell; - + /// define a set in which the found master surface elements are stored std::set master_surface_elements; std::set::iterator it_set; - + /// find all master elements that are in the considered region for(UInt cl = 0; cl < nb_neighbor_cells; ++cl) { - + /// get cell number and offset range UInt considered_cell = neighbor_cells[cl]; UInt min_master_offset = master_nodes_cell_offset[considered_cell]; UInt max_master_offset = master_nodes_cell_offset[considered_cell + 1]; - + for(UInt mn = min_master_offset; mn < max_master_offset; ++mn) { UInt master_node = master_nodes_cell[mn]; UInt min_element_offset = node_to_elements_offset_val[master_node]; UInt max_element_offset = node_to_elements_offset_val[master_node + 1]; - + for(UInt el = min_element_offset; el < max_element_offset; ++el) { - if(surface_id_val[node_to_elements_val[el]] == master_surface) + if(surface_id_val[node_to_elements_val[el]] == master_surface) master_surface_elements.insert(node_to_elements_val[el]); } } } UInt min_impactor_offset = impactor_nodes_cell_offset[current_cell]; UInt max_impactor_offset = impactor_nodes_cell_offset[current_cell + 1]; - + for(UInt imp = min_impactor_offset; imp < max_impactor_offset; ++imp) { UInt impactor_node = impactor_nodes_cell[imp]; neighbor_list->impactor_nodes.push_back(impactor_node); //impactor_nodes_val[neighbor_list->nb_nodes++] = impactor_node; for(it_set = master_surface_elements.begin(); it_set != master_surface_elements.end(); it_set++) { tmp_facets.push_back(*it_set); } tmp_facets_offset.push_back(master_surface_elements.size()); for(UInt inn = 0; inn < nb_impactor_nodes; ++inn) { if(impactor_nodes_cell[inn] == impactor_node) { visited_node_val[inn] = true; break; } } } } } tmp_facets_offset.resize(tmp_facets_offset.getSize()+1); // increase size off offset table by one UInt * tmp_facets_offset_val = tmp_facets_offset.values; - + for (UInt i = 1; i < neighbor_list->impactor_nodes.getSize(); ++i) tmp_facets_offset_val[i] += tmp_facets_offset_val[i - 1]; for (UInt i = neighbor_list->impactor_nodes.getSize(); i > 0; --i) tmp_facets_offset_val[i] = tmp_facets_offset_val[i - 1]; tmp_facets_offset_val[0] = 0; - + delete visited_node; - + } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template -void RegularGridNeighborStructure::constructNodesNeighborList(Int directional_nb_cells[spatial_dimension], - UInt nb_cells, - Vector * cell, - UInt * impactor_nodes_cell_offset, - UInt * impactor_nodes_cell, - UInt * master_nodes_cell_offset, +template +void RegularGridNeighborStructure::constructNodesNeighborList(Int directional_nb_cells[spatial_dimension], + UInt nb_cells, + Vector * cell, + UInt * impactor_nodes_cell_offset, + UInt * impactor_nodes_cell, + UInt * master_nodes_cell_offset, UInt * master_nodes_cell) { AKANTU_DEBUG_IN(); - + NodesNeighborList * nodes_neighbor_list = dynamic_cast(neighbor_list); UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; UInt nb_surfaces = mesh.getNbSurfaces(); UInt nb_surface_nodes = surface_to_nodes_offset[nb_surfaces]; Int * cell_val = cell->values; UInt nb_impactor_nodes = impactor_nodes_cell_offset[nb_cells]; /// define maximal number of neighbor cells and include it-self UInt max_nb_neighbor_cells; if(spatial_dimension == 2) { max_nb_neighbor_cells = 9; } else if(spatial_dimension == 3) { max_nb_neighbor_cells = 27; } UInt neighbor_cells[max_nb_neighbor_cells]; - + for(UInt in = 0; in < nb_impactor_nodes; ++in) { UInt current_impactor_node = impactor_nodes_cell[in]; nodes_neighbor_list->impactor_nodes.push_back(current_impactor_node); //nodes_neighbor_list->nb_nodes += 1; - + /// find and store cell numbers of neighbor cells and it-self Int tmp_cell = - std::numeric_limits::max();; bool init = false; for(UInt i = 0; i < nb_surface_nodes; ++i) { if(surface_to_nodes[i] == current_impactor_node) { tmp_cell = std::max(tmp_cell, cell_val[i]); init = true; } } - AKANTU_DEBUG_ASSERT(init, "Cell number of node is not initialized"); - AKANTU_DEBUG_ASSERT(tmp_cell >= 0, "Bad cell index. Found cell nb of impactor = " << tmp_cell << " This case normally should not happen!"); + AKANTU_DEBUG_ASSERT(init, "Cell number of node is not initialized"); + AKANTU_DEBUG_ASSERT(tmp_cell >= 0, "Bad cell index. Found cell nb of impactor = " << tmp_cell << " This case normally should not happen!"); UInt current_cell = tmp_cell; UInt nb_neighbor_cells = computeNeighborCells(current_cell, neighbor_cells, directional_nb_cells); neighbor_cells[nb_neighbor_cells++] = current_cell; UInt tmp_nb_master_nodes = 0; /// find all master elements that are in the considered region for(UInt cl = 0; cl < nb_neighbor_cells; ++cl) { - + /// get cell number and offset range UInt considered_cell = neighbor_cells[cl]; UInt min_master_offset = master_nodes_cell_offset[considered_cell]; UInt max_master_offset = master_nodes_cell_offset[considered_cell + 1]; - + for(UInt mn = min_master_offset; mn < max_master_offset; ++mn) { UInt master_node = master_nodes_cell[mn]; nodes_neighbor_list->master_nodes.push_back(master_node); } tmp_nb_master_nodes += max_master_offset - min_master_offset; } nodes_neighbor_list->master_nodes_offset.push_back(tmp_nb_master_nodes); } nodes_neighbor_list->master_nodes_offset.resize(nodes_neighbor_list->master_nodes_offset.getSize()+1); // increase size off offset table by one UInt * master_nodes_offset_val = nodes_neighbor_list->master_nodes_offset.values; - + for (UInt i = 1; i < nodes_neighbor_list->impactor_nodes.getSize(); ++i) master_nodes_offset_val[i] += master_nodes_offset_val[i - 1]; for (UInt i = nodes_neighbor_list->impactor_nodes.getSize(); i > 0; --i) master_nodes_offset_val[i] = master_nodes_offset_val[i - 1]; master_nodes_offset_val[0] = 0; - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -template +template bool RegularGridNeighborStructure::check() { - + AKANTU_DEBUG_IN(); bool need_update = false; UInt nb_surfaces = mesh.getNbSurfaces(); Real * current_increment = contact_search.getContact().getModel().getIncrement().values; Real max[spatial_dimension]; - + /// initialize max table with extrem values for(UInt dim = 0; dim < spatial_dimension; ++dim) max[dim] = 0.0; // get the nodes that are on the surfaces UInt * surface_to_nodes_offset = contact_search.getContact().getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact_search.getContact().getSurfaceToNodes().values; /// find maximal increment of surface nodes in all directions for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_increment = current_increment[cur_node * spatial_dimension + dim]; max[dim] = std::max(max[dim], fabs(cur_increment)); } - } + } } - + /// test if the total increment is larger than a critical distance for(UInt dim = 0; dim < spatial_dimension; ++dim) { max_increment[dim] += max[dim]; if(max_increment[dim] > security_factor[dim] * grid_spacing[dim]) { need_update = true; break; } } AKANTU_DEBUG_OUT(); return need_update; } /* -------------------------------------------------------------------------- */ -template +template void RegularGridNeighborStructure::setMinimalGridSpacing() { AKANTU_DEBUG_IN(); Real min_cell_size[3] = {0.,0.,0.}; Real margin = 1.2; Real * node_current_position = contact_search.getContact().getModel().getCurrentPosition().values; const Mesh::ConnectivityTypeList & type_list = this->mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; /// find existing surface element types UInt nb_facet_types = 0; ElementType facet_type[_max_element_type]; - + for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(mesh.getSpatialDimension(type) == spatial_dimension) { facet_type[nb_facet_types++] = mesh.getFacetElementType(type); } } /// loop over all existing surface element types for (UInt el_type = 0; el_type < nb_facet_types; ++el_type) { ElementType type = facet_type[el_type]; UInt nb_element = mesh.getNbElement(type); UInt nb_nodes_element = mesh.getNbNodesPerElement(type); - UInt * conn = mesh.getConnectivity(type).values; + UInt * conn = mesh.getConnectivity(type, _not_ghost).values; + + const UInt *surf_id_val = mesh.getSurfaceID(type, _not_ghost).values; - const UInt *surf_id_val = mesh.getSurfaceId(type).values; - for(UInt e = 0; e < nb_element; ++e) { if(surf_id_val[e] == master_surface) { Real min_coord[3]; Real max_coord[3]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { min_coord[dim] = std::numeric_limits::max(); max_coord[dim] = - std::numeric_limits::max(); } for(UInt n = 0; n < nb_nodes_element; ++n) { UInt node = conn[e*nb_nodes_element + n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_position = node_current_position[node*spatial_dimension + dim]; min_coord[dim] = std::min(min_coord[dim], cur_position); max_coord[dim] = std::max(max_coord[dim], cur_position); - } + } } for(UInt dim = 0; dim < spatial_dimension; ++dim) { min_cell_size[dim] = std::max(min_cell_size[dim], max_coord[dim] - min_coord[dim]); } } } } // find largest grid_spacing in all direction Real max_grid_spacing = 0.; for(UInt dim = 0; dim < spatial_dimension; ++dim) max_grid_spacing = std::max(max_grid_spacing, min_cell_size[dim]); // use the max grid spacing for all direction (multiplied by a margin) for(UInt dim = 0; dim < spatial_dimension; ++dim) this->grid_spacing[dim] = margin * max_grid_spacing; std::cout << "The grid spacing used for the regular grid is of size: " << this->grid_spacing[0] << std::endl; - + AKANTU_DEBUG_OUT(); } template class RegularGridNeighborStructure<2>; template class RegularGridNeighborStructure<3>; __END_AKANTU__ diff --git a/model/solid_mechanics/contact_neighbor_structure.cc b/model/solid_mechanics/contact_neighbor_structure.cc index ea1acff57..dce5a28b0 100644 --- a/model/solid_mechanics/contact_neighbor_structure.cc +++ b/model/solid_mechanics/contact_neighbor_structure.cc @@ -1,91 +1,91 @@ /** * @file contact_neighbor_structure.cc * @author David Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @date Fri Oct 8 12:42:26 2010 * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ NeighborList::NeighborList() : impactor_nodes(Vector(0, 1, "impactors")) { AKANTU_DEBUG_IN(); - for (UInt i = 0; i < _max_element_type; ++i) { - facets_offset[i] = NULL; - facets [i] = NULL; - } + // for (UInt i = 0; i < _max_element_type; ++i) { + // facets_offset[i] = NULL; + // facets [i] = NULL; + // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ NeighborList::~NeighborList() { AKANTU_DEBUG_IN(); - for (UInt i = 0; i < _max_element_type; ++i) { - if(facets_offset[i]) delete facets_offset[i]; - if(facets [i]) delete facets [i]; - } + // for (UInt i = 0; i < _max_element_type; ++i) { + // if(facets_offset[i]) delete facets_offset[i]; + // if(facets [i]) delete facets [i]; + // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactNeighborStructure::ContactNeighborStructure(const ContactSearch & contact_search, const Surface & master_surface, const ContactNeighborStructureType & type, const ContactNeighborStructureID & id) : id(id), contact_search(contact_search), master_surface(master_surface), type(type) { AKANTU_DEBUG_IN(); neighbor_list = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactNeighborStructure::~ContactNeighborStructure() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactNeighborStructure::check() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ERROR("Check not implemented for this neighbors structure : " << id); AKANTU_DEBUG_OUT(); return false; } __END_AKANTU__ diff --git a/model/solid_mechanics/contact_search.cc b/model/solid_mechanics/contact_search.cc index d6bf2f49f..5b84ce883 100644 --- a/model/solid_mechanics/contact_search.cc +++ b/model/solid_mechanics/contact_search.cc @@ -1,255 +1,247 @@ /** * @file contact_search.cc * @author David Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @date Fri Oct 8 11:46:34 2010 * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "contact_search.hh" #include "contact.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "grid_2d_neighbor_structure.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ PenetrationList::PenetrationList() : penetrating_nodes(Vector(0, 1, "penetrating_nodes")) { AKANTU_DEBUG_IN(); - for (UInt i = 0; i < _max_element_type; ++i) { - penetrated_facets_offset[i] = NULL; - penetrated_facets [i] = NULL; - facets_normals [i] = NULL; - gaps [i] = NULL; - projected_positions [i] = NULL; - } - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ PenetrationList::~PenetrationList() { AKANTU_DEBUG_IN(); - for (UInt i = 0; i < _max_element_type; ++i) { - if(penetrated_facets_offset[i]) delete penetrated_facets_offset[i]; - if(penetrated_facets [i]) delete penetrated_facets [i]; - if(facets_normals [i]) delete facets_normals [i]; - if(gaps [i]) delete gaps [i]; - if(projected_positions [i]) delete projected_positions [i]; - } + // for (UInt i = 0; i < _max_element_type; ++i) { + // if(penetrated_facets_offset[i]) delete penetrated_facets_offset[i]; + // if(penetrated_facets [i]) delete penetrated_facets [i]; + // if(facets_normals [i]) delete facets_normals [i]; + // if(gaps [i]) delete gaps [i]; + // if(projected_positions [i]) delete projected_positions [i]; + // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch::ContactSearch(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id) : id(id), contact(contact), neighbors_structure_type(neighbors_structure_type), type(type) { AKANTU_DEBUG_IN(); contact.setContactSearch(*this); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ ContactSearch::~ContactSearch() { AKANTU_DEBUG_IN(); std::map::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { delete it->second; } neighbors_structure.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initSearch() { AKANTU_DEBUG_IN(); - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initNeighborStructure() { AKANTU_DEBUG_IN(); std::map::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { it->second->initNeighborStructure(); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::initNeighborStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); - + std::map::iterator it; for (it = neighbors_structure.begin(); it != neighbors_structure.end(); ++it) { if(it->first == master_surface) it->second->initNeighborStructure(); } - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::addMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) == neighbors_structure.end(), "Master surface already registered in the search object " << id); ContactNeighborStructure * tmp_neighbors_structure = NULL; std::stringstream sstr; sstr << id << ":contact_neighbor_structure:" << neighbors_structure_type << ":" << master_surface; switch(neighbors_structure_type) { case _cnst_regular_grid : { Mesh & mesh = contact.getModel().getFEM().getMesh(); if (mesh.getSpatialDimension() == 2) { tmp_neighbors_structure = new RegularGridNeighborStructure<2>(*this, master_surface, neighbors_structure_type, sstr.str()); } else if(mesh.getSpatialDimension() == 3) { tmp_neighbors_structure = new RegularGridNeighborStructure<3>(*this, master_surface, neighbors_structure_type, sstr.str()); } - else - AKANTU_DEBUG_ERROR("RegularGridNeighborStructure does not exist for dimension: " + else + AKANTU_DEBUG_ERROR("RegularGridNeighborStructure does not exist for dimension: " << mesh.getSpatialDimension()); break; } case _cnst_2d_grid : { tmp_neighbors_structure = new Grid2dNeighborStructure(*this, master_surface, neighbors_structure_type, sstr.str()); break; } case _cnst_not_defined : // tmp_neighbors_structure = new ContactNeighborStructureGrid2d(this, master_surface, sstr.str()); AKANTU_DEBUG_ERROR("Not a valid neighbors structure type : " << neighbors_structure_type); break; } neighbors_structure[master_surface] = tmp_neighbors_structure; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::removeMasterSurface(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); delete neighbors_structure[master_surface]; neighbors_structure.erase(neighbors_structure.find(master_surface)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void ContactSearch::updateStructure(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); neighbors_structure[master_surface]->update(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool ContactSearch::checkIfUpdateStructureNeeded(const Surface & master_surface) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(neighbors_structure.find(master_surface) != neighbors_structure.end(), "Master surface not registered in the search object " << id); bool check = neighbors_structure[master_surface]->check(); AKANTU_DEBUG_OUT(); return check; } /* -------------------------------------------------------------------------- */ const ContactNeighborStructure & ContactSearch::getContactNeighborStructure(const Surface & master_surface) const { AKANTU_DEBUG_IN(); std::map::const_iterator it = neighbors_structure.find(master_surface); AKANTU_DEBUG_ASSERT(it != neighbors_structure.end(), "Master surface not registred in contact search."); AKANTU_DEBUG_OUT(); return *(it->second); } /* -------------------------------------------------------------------------- */ void ContactSearch::computeMaxIncrement(Real * max_increment) { AKANTU_DEBUG_IN(); - + UInt spatial_dimension = contact.getModel().getFEM().getMesh().getSpatialDimension(); UInt nb_surfaces = contact.getModel().getFEM().getMesh().getNbSurfaces(); Real * current_increment = contact.getModel().getIncrement().values; /// initialize max table with zeros for(UInt dim = 0; dim < spatial_dimension; ++dim) max_increment[dim] = 0.0; // get the nodes that are on the surfaces UInt * surface_to_nodes_offset = contact.getSurfaceToNodesOffset().values; UInt * surface_to_nodes = contact.getSurfaceToNodes().values; /// find maximal increment of surface nodes in all directions for(UInt surf = 0; surf < nb_surfaces; ++surf) { UInt min_surf_offset = surface_to_nodes_offset[surf]; UInt max_surf_offset = surface_to_nodes_offset[surf + 1]; for(UInt n = min_surf_offset; n < max_surf_offset; ++n) { UInt cur_node = surface_to_nodes[n]; for(UInt dim = 0; dim < spatial_dimension; ++dim) { Real cur_increment = current_increment[cur_node * spatial_dimension + dim]; max_increment[dim] = std::max(max_increment[dim], fabs(cur_increment)); } - } + } } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/contact_search.hh b/model/solid_mechanics/contact_search.hh index 76d89cf97..309e9a9c8 100644 --- a/model/solid_mechanics/contact_search.hh +++ b/model/solid_mechanics/contact_search.hh @@ -1,149 +1,149 @@ /** * @file contact_search.hh * @author David Kammer * @author Leonardo Snozzi * @author Nicolas Richart * @date Fri Oct 8 10:43:54 2010 * * @brief Interface of the search class for contact * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_CONTACT_SEARCH_HH__ #define __AKANTU_CONTACT_SEARCH_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_vector.hh" #include "contact.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class ContactNeighborStructure; } __BEGIN_AKANTU__ class PenetrationList { public: PenetrationList(); virtual ~PenetrationList(); public: /// nodes who have penetrated the master surface Vector penetrating_nodes; /// list of penetrated facets ByElementTypeUInt penetrated_facets_offset; ByElementTypeUInt penetrated_facets; /// normal of the penetrated facets ByElementTypeReal facets_normals; /// gap between the penetrated facets and the node ByElementTypeReal gaps; /// position of the node projected on the penetrated facets ByElementTypeReal projected_positions; }; /* -------------------------------------------------------------------------- */ class ContactSearch : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: - + ContactSearch(Contact & contact, const ContactNeighborStructureType & neighbors_structure_type, const ContactSearchType & type, const ContactSearchID & id = "search_contact"); virtual ~ContactSearch(); - + /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// initialize the needed structures virtual void initSearch(); /// initialize all neighbor structures virtual void initNeighborStructure(); /// initialize one neighbor structure virtual void initNeighborStructure(const Surface & master_surface); /// build the penetration list virtual void findPenetration(const Surface & master_surface, PenetrationList & penetration_list) = 0; /// update the neighbor structure virtual void updateStructure(const Surface & master_surface); /// check if the neighbor structure need an update virtual bool checkIfUpdateStructureNeeded(const Surface & master_surface); /// add a new master surface void addMasterSurface(const Surface & master_surface); /// remove a master surface void removeMasterSurface(const Surface & master_surface); private: /// compute the maximal increment for all surface nodes in each direction void computeMaxIncrement(Real * max_increment); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const ContactSearchID &); AKANTU_GET_MACRO(Contact, contact, const Contact &); - + AKANTU_GET_MACRO(Type, type, const ContactSearchType &); const ContactNeighborStructure & getContactNeighborStructure(const Surface & master_surface) const; - + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the object ContactSearchID id; /// associated contact class const Contact & contact; /// type of the neighbors structure to create const ContactNeighborStructureType & neighbors_structure_type; /// structure used to handle neighbors lists std::map neighbors_structure; /// type of contact search object ContactSearchType type; }; __END_AKANTU__ #endif /* __AKANTU_CONTACT_SEARCH_HH__ */ diff --git a/model/solid_mechanics/material.cc b/model/solid_mechanics/material.cc index 9c1777653..fecf83e38 100644 --- a/model/solid_mechanics/material.cc +++ b/model/solid_mechanics/material.cc @@ -1,448 +1,440 @@ /** * @file material.cc * @author Nicolas Richart * @date Tue Jul 27 11:43:41 2010 * * @brief Implementation of the common part of the material class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material.hh" #include "solid_mechanics_model.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ -Material::Material(Model & model, const MaterialID & id) : - Memory(model.getMemoryID()), - id(id), - name(""), - potential_energy_vector(false), - is_init(false) { - +Material::Material(Model & model, const MaterialID & id) : Memory(model.getMemoryID()), + id(id), + name(""), + potential_energy_vector(false), + is_init(false) { AKANTU_DEBUG_IN(); this->model = dynamic_cast(&model); AKANTU_DEBUG_ASSERT(this->model,"model has wrong type: cannot proceed"); spatial_dimension = this->model->getSpatialDimension(); - for(UInt t = _not_defined; t < _max_element_type; ++t) { - this->stress [t] = NULL; - this->strain [t] = NULL; - this->potential_energy [t] = NULL; - this->element_filter [t] = NULL; - this->ghost_stress [t] = NULL; - this->ghost_strain [t] = NULL; - this->ghost_potential_energy[t] = NULL; - this->ghost_element_filter [t] = NULL; - } - /// allocate strain stress for local elements - initInternalVector(strain, spatial_dimension*spatial_dimension, "strain", _not_ghost); - initInternalVector(stress, spatial_dimension*spatial_dimension, "stress", _not_ghost); - - /// allocate strain stress for ghost elements - initInternalVector(ghost_strain, spatial_dimension*spatial_dimension, "strain", _ghost); - initInternalVector(ghost_stress, spatial_dimension*spatial_dimension, "stress", _ghost); + initInternalVector(strain, spatial_dimension*spatial_dimension, "strain"); + initInternalVector(stress, spatial_dimension*spatial_dimension, "stress"); /// for each connectivity types allocate the element filer array of the material - const Mesh::ConnectivityTypeList & type_list = - model.getFEM().getMesh().getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - std::stringstream sstr; sstr << id << ":element_filer:"<< *it; - element_filter[*it] = &(alloc (sstr.str(), 0, 1)); - } - - - const Mesh::ConnectivityTypeList & ghost_type_list = - model.getFEM().getMesh().getConnectivityTypeList(_ghost); - - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - - std::stringstream sstr; sstr << id << ":ghost_element_filer:"<< *it; - ghost_element_filter[*it] = &(alloc (sstr.str(), 0, 1)); + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + + std::string ghost_id = ""; + if (gt == _ghost) ghost_id = "ghost_"; + + const Mesh::ConnectivityTypeList & type_list = + model.getFEM().getMesh().getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; + std::stringstream sstr; sstr << id << ":" << ghost_id << "element_filer:"<< *it; + element_filter(*it, gt) = &(alloc (sstr.str(), 0, 1)); + } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Material::~Material() { AKANTU_DEBUG_IN(); - + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void Material::setParam(const std::string & key, const std::string & value, __attribute__ ((unused)) const MaterialID & id) { if(key == "name") name = std::string(value); else AKANTU_DEBUG_ERROR("Unknown material property : " << key); } /* -------------------------------------------------------------------------- */ void Material::initMaterial() { AKANTU_DEBUG_IN(); - resizeInternalVector(stress,_not_ghost); - resizeInternalVector(ghost_stress,_ghost); - resizeInternalVector(strain,_not_ghost); - resizeInternalVector(ghost_strain,_ghost); + resizeInternalVector(stress); + resizeInternalVector(strain); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Material::initInternalVector(ByElementTypeReal & vect, +template +void Material::initInternalVector(ByElementTypeVector & vect, UInt nb_component, - const std::string & vect_id, - GhostType ghost_type) { + const ID & vect_id) { AKANTU_DEBUG_IN(); - model->getFEM().getMesh().initByElementTypeRealVector(vect, nb_component, spatial_dimension, - id, vect_id, ghost_type); + model->getFEM().getMesh().initByElementTypeVector(vect, nb_component, spatial_dimension, + id, vect_id); + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ -void Material::resizeInternalVector(ByElementTypeReal & vect, - GhostType ghost_type) { +template +void Material::resizeInternalVector(ByElementTypeVector & by_el_type_vect) { AKANTU_DEBUG_IN(); - const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(ghost_type); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; - Vector * elem_filter; - if (ghost_type == _not_ghost) { - elem_filter = element_filter[*it]; - } else if (ghost_type == _ghost) { - elem_filter = ghost_element_filter[*it]; - } + const Mesh::ConnectivityTypeList & type_list = + model->getFEM().getMesh().getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; + + Vector * elem_filter = element_filter(*it, gt); + + UInt nb_element = elem_filter->getSize(); + UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, gt); + UInt new_size = nb_element*nb_quadrature_points; - UInt nb_element = elem_filter->getSize(); - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it); - UInt new_size = nb_element*nb_quadrature_points; + Vector * vect = by_el_type_vect(*it, gt); + UInt size = vect->getSize(); + UInt nb_component = vect->getNbComponent(); - UInt size = vect[*it]->getSize(); - UInt nb_component = vect[*it]->getNbComponent(); - vect[*it]->resize(new_size); - memset(vect[*it]->values + size * nb_component, 0, (new_size - size) * nb_component * sizeof(Real)); + vect->resize(new_size); + memset(vect->values + size * nb_component, 0, (new_size - size) * nb_component * sizeof(T)); + } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the residual by assembling @f$\int_{e} \sigma_e \frac{\partial * \varphi}{\partial X} dX @f$ * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::updateResidual(Vector & current_position, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); Vector & residual = const_cast &>(model->getResidual()); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - Vector * strain_vect; - Vector * stress_vect; - Vector * elem_filter; - const Vector & shapes_derivatives = model->getFEM().getShapesDerivatives(*it,ghost_type); - - if(ghost_type == _not_ghost) { - elem_filter = element_filter[*it]; - strain_vect = strain[*it]; - stress_vect = stress[*it]; - } else { - elem_filter = ghost_element_filter[*it]; - strain_vect = ghost_strain[*it]; - stress_vect = ghost_stress[*it]; - } + const Vector & shapes_derivatives = model->getFEM().getShapesDerivatives(*it, ghost_type); + Vector * elem_filter = element_filter(*it, ghost_type); + Vector * strain_vect = strain(*it, ghost_type); + Vector * stress_vect = stress(*it, ghost_type); + UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it); + UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, ghost_type); UInt nb_element = elem_filter->getSize(); /// compute @f$\nabla u@f$ model->getFEM().gradientOnQuadraturePoints(current_position, *strain_vect, spatial_dimension, *it, ghost_type, elem_filter); /// compute @f$\mathbf{\sigma}_q@f$ from @f$\nabla u@f$ computeStress(*it, ghost_type); /// compute @f$\sigma \frac{\partial \varphi}{\partial X}@f$ by @f$\mathbf{B}^t \mathbf{\sigma}_q@f$ Vector * sigma_dphi_dx = new Vector(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "sigma_x_dphi_/_dX"); Real * shapesd = shapes_derivatives.values; UInt size_of_shapesd = shapes_derivatives.getNbComponent(); Real * shapesd_val; UInt * elem_filter_val = elem_filter->values; Vector * shapesd_filtered = new Vector(nb_element*nb_quadrature_points, size_of_shapes_derivatives, "filtered shapesd"); Real * shapesd_filtered_val = shapesd_filtered->values; for (UInt el = 0; el < nb_element; ++el) { shapesd_val = shapesd + elem_filter_val[el] * size_of_shapesd * nb_quadrature_points; memcpy(shapesd_filtered_val, shapesd_val, size_of_shapesd * nb_quadrature_points * sizeof(Real)); shapesd_filtered_val += size_of_shapesd * nb_quadrature_points; } Math::matrix_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension, *shapesd_filtered, *stress_vect, *sigma_dphi_dx); delete shapesd_filtered; // for (UInt el = 0; el < nb_element; ++el) { // shapesd_val = shapesd + elem_filter_val[el]*size_of_shapesd*nb_quadrature_points; // for (UInt q = 0; q < nb_quadrature_points; ++q) { // Math::matrix_matrixt(nb_nodes_per_element, spatial_dimension, spatial_dimension, // shapesd_val, stress_val, sigma_dphi_dx_val); // shapesd_val += offset_shapesd_val; // stress_val += offset_stress_val; // sigma_dphi_dx_val += offset_sigma_dphi_dx_val; // } // } /** * compute @f$\int \sigma * \frac{\partial \varphi}{\partial X}dX@f$ by @f$ \sum_q \mathbf{B}^t * \mathbf{\sigma}_q \overline w_q J_q@f$ */ Vector * int_sigma_dphi_dx = new Vector(0, nb_nodes_per_element * spatial_dimension, "int_sigma_x_dphi_/_dX"); model->getFEM().integrate(*sigma_dphi_dx, *int_sigma_dphi_dx, size_of_shapes_derivatives, *it, ghost_type, elem_filter); delete sigma_dphi_dx; /// assemble model->getFEM().assembleVector(*int_sigma_dphi_dx, residual, model->getDOFSynchronizer().getLocalDOFEquationNumbers(), residual.getNbComponent(), *it, ghost_type, elem_filter, -1); delete int_sigma_dphi_dx; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /** * Compute the stiffness matrix by assembling @f$\int_{\omega} B^t \times D * \times B d\omega @f$ * * @param[in] current_position nodes postition + displacements * @param[in] ghost_type compute the residual for _ghost or _not_ghost element */ void Material::assembleStiffnessMatrix(Vector & current_position, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; switch(spatial_dimension) { case 1: { assembleStiffnessMatrix<1>(current_position, *it, ghost_type); break; } case 2: { assembleStiffnessMatrix<2>(current_position, *it, ghost_type); break; } case 3: { assembleStiffnessMatrix<3>(current_position, *it, ghost_type); break; } } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void Material::assembleStiffnessMatrix(Vector & current_position, const ElementType & type, GhostType ghost_type) { AKANTU_DEBUG_IN(); SparseMatrix & K = const_cast(model->getStiffnessMatrix()); // const Vector & equation_number = K.getDOFSynchronizer().getDOFEquationNumbers(); - Vector * strain_vect; - // Vector * stress_vect; - Vector * elem_filter; const Vector & shapes_derivatives = model->getFEM().getShapesDerivatives(type,ghost_type); - if(ghost_type == _not_ghost) { - elem_filter = element_filter[type]; - strain_vect = strain[type]; - // stress_vect = stress[type]; - } else { - elem_filter = ghost_element_filter[type]; - strain_vect = ghost_strain[type]; - // stress_vect = ghost_stress[type]; - } + Vector * elem_filter = element_filter(type, ghost_type); + Vector * strain_vect = strain(type, ghost_type); + UInt * elem_filter_val = elem_filter->values; UInt nb_element = elem_filter->getSize(); UInt size_of_shapes_derivatives = shapes_derivatives.getNbComponent(); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(type); + UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(type, ghost_type); model->getFEM().gradientOnQuadraturePoints(current_position, *strain_vect, dim, type, ghost_type, elem_filter); UInt tangent_size = getTangentStiffnessVoigtSize(dim); Vector * tangent_stiffness_matrix = new Vector(nb_element*nb_quadrature_points, tangent_size * tangent_size, "tangent_stiffness_matrix"); computeTangentStiffness(type, *tangent_stiffness_matrix, ghost_type); /// compute @f$\mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ UInt bt_d_b_size = dim * nb_nodes_per_element; Vector * bt_d_b = new Vector(nb_element*nb_quadrature_points, bt_d_b_size * bt_d_b_size, "B^t*D*B"); UInt size_of_b = tangent_size * bt_d_b_size; Real * B = new Real[size_of_b]; Real * Bt_D = new Real[size_of_b]; Real * Bt_D_B = bt_d_b->values; Real * D = tangent_stiffness_matrix->values; UInt offset_bt_d_b = bt_d_b_size * bt_d_b_size; UInt offset_d = tangent_size * tangent_size; for (UInt e = 0; e < nb_element; ++e) { Real * shapes_derivatives_val = shapes_derivatives.values + elem_filter_val[e]*size_of_shapes_derivatives*nb_quadrature_points; for (UInt q = 0; q < nb_quadrature_points; ++q) { transferBMatrixToSymVoigtBMatrix(shapes_derivatives_val, B, nb_nodes_per_element); Math::matrixt_matrix(bt_d_b_size, tangent_size, tangent_size, B, D, Bt_D); Math::matrix_matrix(bt_d_b_size, bt_d_b_size, tangent_size, Bt_D, B, Bt_D_B); shapes_derivatives_val += size_of_shapes_derivatives; D += offset_d; Bt_D_B += offset_bt_d_b; } } delete [] B; delete [] Bt_D; delete tangent_stiffness_matrix; /// compute @f$ k_e = \int_e \mathbf{B}^t * \mathbf{D} * \mathbf{B}@f$ Vector * K_e = new Vector(0, bt_d_b_size * bt_d_b_size, "K_e"); model->getFEM().integrate(*bt_d_b, *K_e, bt_d_b_size * bt_d_b_size, type, ghost_type, elem_filter); delete bt_d_b; model->getFEM().assembleMatrix(*K_e, K, spatial_dimension, type, ghost_type, elem_filter); delete K_e; AKANTU_DEBUG_OUT(); } +/* -------------------------------------------------------------------------- */ +void Material::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { + AKANTU_DEBUG_IN(); + + if(ghost_type != _not_ghost) return; + Real * epot = potential_energy(el_type, ghost_type)->values; + + MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; + + computePotentialEnergy(strain_val, stress_val, epot); + epot++; + + MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; + + AKANTU_DEBUG_OUT(); +} + /* -------------------------------------------------------------------------- */ void Material::computePotentialEnergyByElement() { AKANTU_DEBUG_IN(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(_not_ghost); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(model->getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; - if(potential_energy[*it] == NULL) { - UInt nb_element = element_filter[*it]->getSize(); - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it); + if(!potential_energy.exists(*it, _not_ghost)) { + UInt nb_element = element_filter(*it, _not_ghost)->getSize(); + UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(*it, _not_ghost); std::stringstream sstr; sstr << id << ":potential_energy:"<< *it; - potential_energy[*it] = &(alloc (sstr.str(), nb_element * nb_quadrature_points, - 1, - REAL_INIT_VALUE)); + potential_energy(*it, _not_ghost) = &(alloc (sstr.str(), nb_element * nb_quadrature_points, + 1, + REAL_INIT_VALUE)); } computePotentialEnergy(*it); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Real Material::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; computePotentialEnergyByElement(); /// integrate the potential energy for each type of elements const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(_not_ghost); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(model->getFEM().getMesh().getSpatialDimension(*it) != spatial_dimension) continue; - epot += model->getFEM().integrate(*potential_energy[*it], *it, - _not_ghost, element_filter[*it]); + epot += model->getFEM().integrate(*potential_energy(*it, _not_ghost), *it, + _not_ghost, element_filter(*it, _not_ghost)); } AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ +template void Material::initInternalVector(ByElementTypeVector & vect, + UInt nb_component, + const ID & id); +template void Material::initInternalVector(ByElementTypeVector & vect, + UInt nb_component, + const ID & id); +template void Material::initInternalVector(ByElementTypeVector & vect, + UInt nb_component, + const ID & id); + +template void Material::resizeInternalVector(ByElementTypeVector & vect); +template void Material::resizeInternalVector(ByElementTypeVector & vect); +template void Material::resizeInternalVector(ByElementTypeVector & vect); __END_AKANTU__ diff --git a/model/solid_mechanics/material.hh b/model/solid_mechanics/material.hh index 6330be5be..4cf95a1bf 100644 --- a/model/solid_mechanics/material.hh +++ b/model/solid_mechanics/material.hh @@ -1,316 +1,297 @@ /** * @file material.hh * @author Nicolas Richart * @date Fri Jul 23 09:06:29 2010 * * @brief Mother class for all materials * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_HH__ #define __AKANTU_MATERIAL_HH__ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "aka_memory.hh" #include "fem.hh" #include "mesh.hh" //#include "solid_mechanics_model.hh" #include "static_communicator.hh" /* -------------------------------------------------------------------------- */ namespace akantu { class Model; class SolidMechanicsModel; class CommunicationBuffer; } __BEGIN_AKANTU__ class Material : public Memory { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: Material(Model & model, const MaterialID & id = ""); virtual ~Material(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// read properties virtual void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// initialize the material computed parameter virtual void initMaterial(); /// compute the residual for this material void updateResidual(Vector & current_position, GhostType ghost_type = _not_ghost); /// compute the stiffness matrix void assembleStiffnessMatrix(Vector & current_position, GhostType ghost_type); /// compute the stable time step for an element of size h virtual Real getStableTimeStep(Real h, const Element & element = ElementNull) = 0; /// add an element to the local mesh filter - inline void addElement(ElementType type, UInt element); - - /// add an element to the local mesh filter for ghost element - inline void addGhostElement(ElementType type, UInt element); + inline void addElement(const ElementType & type, + UInt element, + const GhostType & ghost_type); /// function to print the contain of the class virtual void printself(std::ostream & stream, int indent = 0) const = 0; protected: /// constitutive law virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost) = 0; /// compute the tangent stiffness matrix virtual void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost) = 0; /// compute the potential energy virtual void computePotentialEnergy(ElementType el_type, - GhostType ghost_type = _not_ghost) = 0; + GhostType ghost_type = _not_ghost); template void assembleStiffnessMatrix(Vector & current_position, const ElementType & type, GhostType ghost_type); /// transfer the B matrix to a Voigt notation B matrix template inline void transferBMatrixToSymVoigtBMatrix(Real * B, Real * Bvoigt, UInt nb_nodes_per_element) const; inline UInt getTangentStiffnessVoigtSize(UInt spatial_dimension) const; /// compute the potential energy by element void computePotentialEnergyByElement(); /* ------------------------------------------------------------------------ */ /* Function for all materials */ /* ------------------------------------------------------------------------ */ protected: + /// compute the potential energy for on element + inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); + /// allocate an internal vector - void initInternalVector(ByElementTypeReal & vect, + template + void initInternalVector(ByElementTypeVector & vect, UInt nb_component, - const std::string & id, - GhostType ghost_type = _not_ghost); + const ID & id); /// resize an internal vector - void resizeInternalVector(ByElementTypeReal & vect, - GhostType ghost_type = _not_ghost); + template + void resizeInternalVector(ByElementTypeVector & vect); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, SynchronizationTag tag); inline virtual UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag); inline virtual void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag); inline virtual void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: AKANTU_GET_MACRO(ID, id, const MaterialID &); AKANTU_GET_MACRO(Rho, rho, Real); Real getPotentialEnergy(); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementFilter, element_filter, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Strain, strain, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Stress, stress, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(PotentialEnergy, potential_energy, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(ElementFilter, element_filter, UInt); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Strain, strain, Real); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Stress, stress, Real); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(PotentialEnergy, potential_energy, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: /// id of the material MaterialID id; /// spatial dimension UInt spatial_dimension; /// material name std::string name; /// The model to witch the material belong SolidMechanicsModel * model; /// density : rho Real rho; /// stresses arrays ordered by element types ByElementTypeReal stress; /// strains arrays ordered by element types ByElementTypeReal strain; /// list of element handled by the material ByElementTypeUInt element_filter; - /// stresses arrays ordered by element types - ByElementTypeReal ghost_stress; - - /// strains arrays ordered by element types - ByElementTypeReal ghost_strain; - - /// list of element handled by the material - ByElementTypeUInt ghost_element_filter; - /// is the vector for potential energy initialized bool potential_energy_vector; /// potential energy by element ByElementTypeReal potential_energy; - /// potential energy by element - ByElementTypeReal ghost_potential_energy; - /// boolean to know if the material has been initialized bool is_init; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const Material & _this) { _this.printself(stream); return stream; } __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* Auto loop */ /* -------------------------------------------------------------------------- */ #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN \ - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(el_type); \ + UInt nb_quadrature_points = \ + model->getFEM().getNbQuadraturePoints(el_type, ghost_type); \ UInt size_strain = spatial_dimension * spatial_dimension; \ + \ + UInt nb_element = element_filter(el_type, ghost_type)->getSize(); \ + if (nb_element == 0) return; \ \ - UInt nb_element; \ - Real * strain_val; \ - Real * stress_val; \ + Vector * stress_tmp = stress(el_type, ghost_type); \ + stress_tmp->resize(nb_element*nb_quadrature_points); \ + Vector * strain_tmp = strain(el_type, ghost_type); \ \ - if(ghost_type == _not_ghost) { \ - nb_element = element_filter[el_type]->getSize(); \ - stress[el_type]->resize(nb_element*nb_quadrature_points); \ - strain_val = strain[el_type]->values; \ - stress_val = stress[el_type]->values; \ - } else { \ - nb_element = ghost_element_filter[el_type]->getSize(); \ - ghost_stress[el_type]->resize(nb_element*nb_quadrature_points); \ - strain_val = ghost_strain[el_type]->values; \ - stress_val = ghost_stress[el_type]->values; \ - } \ + Real * strain_val = strain_tmp->values; \ + Real * stress_val = stress_tmp->values; \ \ - if (nb_element == 0) return; \ \ for (UInt el = 0; el < nb_element; ++el) { \ for (UInt q = 0; q < nb_quadrature_points; ++q) { \ #define MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END \ strain_val += size_strain; \ stress_val += size_strain; \ } \ - } \ + } \ #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent) \ - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(el_type); \ - UInt size_strain = spatial_dimension * spatial_dimension; \ - \ - UInt nb_element; \ - Real * strain_val; \ - Real * tangent_val; \ + UInt nb_quadrature_points = \ + model->getFEM().getNbQuadraturePoints(el_type, ghost_type); \ + UInt size_strain = spatial_dimension * spatial_dimension; \ + \ + UInt nb_element = element_filter(el_type, ghost_type)->getSize(); \ + if (nb_element == 0) return; \ + \ + Vector * stress_tmp = stress(el_type, ghost_type); \ + stress_tmp->resize(nb_element*nb_quadrature_points); \ + Vector * strain_tmp = strain(el_type, ghost_type); \ \ - if(ghost_type == _not_ghost) { \ - nb_element = element_filter[el_type]->getSize(); \ - stress[el_type]->resize(nb_element*nb_quadrature_points); \ - strain_val = strain[el_type]->values; \ - } else { \ - nb_element = ghost_element_filter[el_type]->getSize(); \ - ghost_stress[el_type]->resize(nb_element*nb_quadrature_points); \ - strain_val = ghost_strain[el_type]->values; \ - } \ - tangent_val = tangent.values; \ + Real * strain_val = strain_tmp->values; \ + Real * stress_val = stress_tmp->values; \ + \ + Real * tangent_val = tangent.values; \ UInt size_tangent = getTangentStiffnessVoigtSize(spatial_dimension); \ size_tangent *= size_tangent; \ \ - if (nb_element == 0) return; \ \ for (UInt el = 0; el < nb_element; ++el) { \ for (UInt q = 0; q < nb_quadrature_points; ++q) { \ #define MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END \ strain_val += size_strain; \ tangent_val += size_tangent; \ } \ } \ /* -------------------------------------------------------------------------- */ /* Material list */ /* -------------------------------------------------------------------------- */ #include "materials/material_elastic.hh" #include "materials/material_elastic_caughey.hh" #include "materials/material_damage.hh" #include "materials/material_mazars.hh" #include "materials/material_neohookean.hh" #endif /* __AKANTU_MATERIAL_HH__ */ diff --git a/model/solid_mechanics/material_inline_impl.cc b/model/solid_mechanics/material_inline_impl.cc index dbe7dd065..8247490e3 100644 --- a/model/solid_mechanics/material_inline_impl.cc +++ b/model/solid_mechanics/material_inline_impl.cc @@ -1,130 +1,136 @@ /** * @file material_inline_impl.cc * @author Nicolas Richart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the class material * * @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 . * */ /* -------------------------------------------------------------------------- */ -inline void Material::addElement(ElementType type, UInt element) { - element_filter[type]->push_back(element); -} - -/* -------------------------------------------------------------------------- */ -inline void Material::addGhostElement(ElementType type, UInt element) { - ghost_element_filter[type]->push_back(element); +inline void Material::addElement(const ElementType & type, + UInt element, + const GhostType & ghost_type) { + element_filter(type, ghost_type)->push_back(element); } /* -------------------------------------------------------------------------- */ inline UInt Material::getTangentStiffnessVoigtSize(UInt dim) const { return (dim * (dim - 1) / 2 + dim); } +/* -------------------------------------------------------------------------- */ +inline void Material::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { + *epot = 0.; + for (UInt i = 0, t = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j, ++t) + (*epot) += sigma[t] * F[t] ; + + *epot *= .5; +} /* -------------------------------------------------------------------------- */ template inline void Material::transferBMatrixToSymVoigtBMatrix(Real * B, Real * Bvoigt, UInt nb_nodes_per_element) const { UInt size = getTangentStiffnessVoigtSize(dim) * nb_nodes_per_element * dim; memset(Bvoigt, 0, size * sizeof(Real)); for (UInt i = 0; i < dim; ++i) { Real * Bvoigt_tmp = Bvoigt + i * (dim * nb_nodes_per_element + 1); Real * Btmp = B + i; for (UInt n = 0; n < nb_nodes_per_element; ++n) { *Bvoigt_tmp = *Btmp; Btmp += dim; Bvoigt_tmp += dim; } } if(dim == 2) { ///in 2D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{\partial N_i}{\partial y}]@f$ row Real * Bvoigt_tmp = Bvoigt + dim * nb_nodes_per_element * 2; for (UInt n = 0; n < nb_nodes_per_element; ++n) { Bvoigt_tmp[1] = B[n * dim + 0]; Bvoigt_tmp[0] = B[n * dim + 1]; Bvoigt_tmp += dim; } } if(dim == 3) { UInt Bvoigt_wcol = dim * nb_nodes_per_element; for (UInt n = 0; n < nb_nodes_per_element; ++n) { Real dndx = B[n * dim + 0]; Real dndy = B[n * dim + 1]; Real dndz = B[n * dim + 2]; UInt Bni_off = n * dim; ///in 3D, fill the @f$ [0, \frac{\partial N_i}{\partial y}, \frac{N_i}{\partial z}]@f$ row Bvoigt[3 * Bvoigt_wcol + Bni_off + 1] = dndz; Bvoigt[3 * Bvoigt_wcol + Bni_off + 2] = dndy; ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, 0, \frac{N_i}{\partial z}]@f$ row Bvoigt[4 * Bvoigt_wcol + Bni_off + 0] = dndz; Bvoigt[4 * Bvoigt_wcol + Bni_off + 2] = dndx; ///in 3D, fill the @f$ [\frac{\partial N_i}{\partial x}, \frac{N_i}{\partial y}, 0]@f$ row Bvoigt[5 * Bvoigt_wcol + Bni_off + 0] = dndy; Bvoigt[5 * Bvoigt_wcol + Bni_off + 1] = dndx; } } } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbDataToPack(__attribute__ ((unused)) const Element & element, __attribute__ ((unused)) SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); return 0; } /* -------------------------------------------------------------------------- */ inline UInt Material::getNbDataToUnpack(__attribute__ ((unused)) const Element & element, __attribute__ ((unused)) SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); return 0; } /* -------------------------------------------------------------------------- */ inline void Material::packData(__attribute__ ((unused)) CommunicationBuffer & buffer, __attribute__ ((unused)) const Element & element, __attribute__ ((unused)) SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void Material::unpackData(__attribute__ ((unused)) CommunicationBuffer & buffer, __attribute__ ((unused)) const Element & element, __attribute__ ((unused)) SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_OUT(); } diff --git a/model/solid_mechanics/materials/material_damage.cc b/model/solid_mechanics/materials/material_damage.cc index 715a38cb3..454228e98 100644 --- a/model/solid_mechanics/materials/material_damage.cc +++ b/model/solid_mechanics/materials/material_damage.cc @@ -1,152 +1,112 @@ /** * @file material_damage.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the damage material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material_damage.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialDamage::MaterialDamage(Model & model, const MaterialID & id) : - Material(model, id) { + MaterialElastic(model, id) { AKANTU_DEBUG_IN(); - rho = 0; - E = 0; - nu = 1./2.; Yd = 50; Sd = 5000; - initInternalVector(this->ghost_damage,1,"damage",_ghost); - initInternalVector(this->damage,1,"damage"); + + initInternalVector(this->damage, 1, "damage"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::initMaterial() { AKANTU_DEBUG_IN(); - Material::initMaterial(); + MaterialElastic::initMaterial(); - lambda = nu * E / ((1 + nu) * (1 - 2*nu)); - mu = E / (2 * (1 + nu)); - kpa = lambda + 2./3. * mu; resizeInternalVector(this->damage); - resizeInternalVector(this->ghost_damage,_ghost); + is_init = true; + AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialDamage::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; Real * dam ; - if(ghost_type==_ghost) - dam=ghost_damage[el_type]->values; - else - dam= damage[el_type]->values; + dam = damage(el_type, ghost_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; - // for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; - - computeStress(F, sigma,*dam); + computeStress(F, sigma, *dam); ++dam; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -void MaterialDamage::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { - AKANTU_DEBUG_IN(); - - if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; - - computePotentialEnergy(strain_val, stress_val, epot); - epot++; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; - - AKANTU_DEBUG_OUT(); -} - - /* -------------------------------------------------------------------------- */ void MaterialDamage::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); - if(key == "rho") { sstr >> rho; } - else if(key == "E") { sstr >> E; } - else if(key == "nu") { sstr >> nu; } - else if(key == "Yd") { sstr >> Yd; } + if(key == "Yd") { sstr >> Yd; } else if(key == "Sd") { sstr >> Sd; } - else { Material::setParam(key, value, id); } + else { MaterialElastic::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialDamage::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_damage> [" << std::endl; - stream << space << " + id : " << id << std::endl; - stream << space << " + name : " << name << std::endl; - stream << space << " + density : " << rho << std::endl; - stream << space << " + Young's modulus : " << E << std::endl; - stream << space << " + Poisson's ratio : " << nu << std::endl; stream << space << " + Yd : " << Yd << std::endl; stream << space << " + Sd : " << Sd << std::endl; - if(is_init) { - stream << space << " + First Lamé coefficient : " << lambda << std::endl; - stream << space << " + Second Lamé coefficient : " << mu << std::endl; - stream << space << " + Bulk coefficient : " << kpa << std::endl; - } + MaterialElastic::printself(stream, indent + 1); stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_damage.hh b/model/solid_mechanics/materials/material_damage.hh index 05ffb712a..75febdc08 100644 --- a/model/solid_mechanics/materials/material_damage.hh +++ b/model/solid_mechanics/materials/material_damage.hh @@ -1,144 +1,120 @@ /** * @file material_damage.hh * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_DAMAGE_HH__ #define __AKANTU_MATERIAL_DAMAGE_HH__ __BEGIN_AKANTU__ -class MaterialDamage : public Material { +/** + * Material damage + * + * parameters in the material files : + * - Yd : (default: 50) + * - Sd : (default: 5000) + */ +class MaterialDamage : public MaterialElastic { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialDamage(Model & model, const MaterialID & id = ""); virtual ~MaterialDamage() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma,Real & damage); - /// compute the potential energy for all elements - void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); - - /// compute the potential energy for on element - inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); - /// Compute the tangent stiffness matrix for implicit for a given type void computeTangentStiffness(__attribute__ ((unused)) const ElementType & type, __attribute__ ((unused)) Vector & tangent_matrix, __attribute__ ((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); }; - - /// compute the celerity of wave in the material - inline Real celerity(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - /// get the stable time step - inline Real getStableTimeStep(Real h, const Element & element); - - /// return damage value - ByElementTypeReal & getDamage(){return damage;}; + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ - - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Damage, damage, const Vector &); -private: - - /// the young modulus - Real E; - - /// Poisson coefficient - Real nu; - - /// First Lamé coefficient - Real lambda; - - /// Second Lamé coefficient (shear modulus) - Real mu; +protected: /// resistance to damage Real Yd; /// damage threshold Real Sd; - /// Bulk modulus - Real kpa; - /// damage internal variable ByElementTypeReal damage; - ByElementTypeReal ghost_damage; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_damage_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialDamage & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_DAMAGE_HH__ */ diff --git a/model/solid_mechanics/materials/material_damage_inline_impl.cc b/model/solid_mechanics/materials/material_damage_inline_impl.cc index 7db4c19e4..26c75f57f 100644 --- a/model/solid_mechanics/materials/material_damage_inline_impl.cc +++ b/model/solid_mechanics/materials/material_damage_inline_impl.cc @@ -1,93 +1,73 @@ /** * @file material_damage_inline_impl.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material damage * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline void MaterialDamage::computeStress(Real * F, Real * sigma, Real & dam) { Real trace = F[0] + F[4] + F[8]; /// \F_{11} + \F_{22} + \F_{33} /// \sigma_{ij} = \lamda * \F_{kk} * \delta_{ij} + 2 * \mu * \F_{ij} sigma[0] = lambda * trace + 2*mu*F[0]; sigma[4] = lambda * trace + 2*mu*F[4]; sigma[8] = lambda * trace + 2*mu*F[8]; sigma[1] = sigma[3] = mu * (F[1] + F[3]); sigma[2] = sigma[6] = mu * (F[2] + F[6]); sigma[5] = sigma[7] = mu * (F[5] + F[7]); Real Y = sigma[0]*F[0] + sigma[1]*F[1] + sigma[2]*F[2] + sigma[3]*F[3] + sigma[4]*F[4] + sigma[5]*F[5] + sigma[6]*F[6] + sigma[7]*F[7] + sigma[8]*F[8]; Y *= 0.5; Real Fd = Y - Yd - Sd*dam; if (Fd > 0) dam = (Y - Yd) / Sd; dam = std::min(dam,1.); sigma[0] *= 1-dam; sigma[4] *= 1-dam; sigma[8] *= 1-dam; sigma[1] *= 1-dam; sigma[3] *= 1-dam; sigma[2] *= 1-dam; sigma[6] *= 1-dam; sigma[5] *= 1-dam; sigma[7] *= 1-dam; } - -/* -------------------------------------------------------------------------- */ -inline void MaterialDamage::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { - *epot = 0.; - for (UInt i = 0, t = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j, ++t) - *epot += sigma[t] * F[t]; - *epot *= .5; -} - -/* -------------------------------------------------------------------------- */ -inline Real MaterialDamage::celerity() { - return sqrt(E/rho); -} - -/* -------------------------------------------------------------------------- */ -inline Real MaterialDamage::getStableTimeStep(Real h, - __attribute__ ((unused)) const Element & element) { - return (h/celerity()); -} diff --git a/model/solid_mechanics/materials/material_elastic.cc b/model/solid_mechanics/materials/material_elastic.cc index d971dfa29..8586fe01a 100644 --- a/model/solid_mechanics/materials/material_elastic.cc +++ b/model/solid_mechanics/materials/material_elastic.cc @@ -1,156 +1,139 @@ /** * @file material_elastic.cc * @author Nicolas Richart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the elastic material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material_elastic.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialElastic::MaterialElastic(Model & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; - plain_stress = false; + plane_stress = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); - if(plain_stress) + if(plane_stress) lambda = 2 * lambda * mu / (lambda + 2 * mu); kpa = lambda + 2./3. * mu; is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; // for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; computeStress(F, sigma); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElastic::computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type) { switch(spatial_dimension) { case 1: { computeTangentStiffnessByDim<1>(el_type, tangent_matrix, ghost_type); break; } case 2: { computeTangentStiffnessByDim<2>(el_type, tangent_matrix, ghost_type); break; } case 3: { computeTangentStiffnessByDim<3>(el_type, tangent_matrix, ghost_type); break; } } } -/* -------------------------------------------------------------------------- */ -void MaterialElastic::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { - AKANTU_DEBUG_IN(); - - if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; - - computePotentialEnergy(strain_val, stress_val, epot); - epot++; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; - - AKANTU_DEBUG_OUT(); -} - /* -------------------------------------------------------------------------- */ void MaterialElastic::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "rho") { sstr >> rho; } else if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } - else if(key == "Plain_Stress") { sstr >> plain_stress; } + else if(key == "Plane_Stress") { sstr >> plane_stress; } else { Material::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialElastic::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_elastic> [" << std::endl; - if(!plain_stress) - stream << space << " + Plain strain" << std::endl; + if(!plane_stress) + stream << space << " + Plane strain" << std::endl; else - stream << space << " + Plain stress" << std::endl; + stream << space << " + Plane stress" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; if(is_init) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_elastic.hh b/model/solid_mechanics/materials/material_elastic.hh index 1785cb9ab..f8e77e7a6 100644 --- a/model/solid_mechanics/materials/material_elastic.hh +++ b/model/solid_mechanics/materials/material_elastic.hh @@ -1,148 +1,141 @@ /** * @file material_elastic.hh * @author Nicolas Richart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_HH__ #define __AKANTU_MATERIAL_ELASTIC_HH__ __BEGIN_AKANTU__ /** * Material elastic isotropic * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) - * - Plain_Stress : if 0: plain strain, else: plain stress (default: 0) + * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) */ class MaterialElastic : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElastic(Model & model, const MaterialID & id = ""); virtual ~MaterialElastic() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: virtual void initMaterial(); virtual void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type virtual void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost); - /// compute the potential energy for all elements - virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); - - /// compute the potential energy for on element - inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); - - /// compute the celerity of wave in the material inline Real celerity(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma); // /// compute the tangent stiffness matrix for an element type template void computeTangentStiffnessByDim(akantu::ElementType, akantu::Vector& tangent_matrix, akantu::GhostType); // /// compute the tangent stiffness matrix for an element template void computeTangentStiffness(Real * tangent); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h, const Element & element); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ -private: +protected: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// Bulk modulus Real kpa; - /// Plain stress or plain strain - bool plain_stress; + /// Plane stress or plane strain + bool plane_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_elastic_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialElastic & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_HH__ */ diff --git a/model/solid_mechanics/materials/material_elastic_caughey.cc b/model/solid_mechanics/materials/material_elastic_caughey.cc index 93b94a849..2f09c19f9 100644 --- a/model/solid_mechanics/materials/material_elastic_caughey.cc +++ b/model/solid_mechanics/materials/material_elastic_caughey.cc @@ -1,169 +1,153 @@ /** * @file material_elastic_caughey.cc * @author David Kammer * @author Nicolas Richart * @date Wed May 4 15:25:52 2011 * * @brief Special. of the material class for the caughey viscoelastic material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material_elastic_caughey.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialElasticCaughey::MaterialElasticCaughey(Model & model, const MaterialID & id) : MaterialElastic(model, id) { AKANTU_DEBUG_IN(); alpha = 0.; UInt spatial_dimension = this->model->getSpatialDimension(); UInt stress_size = spatial_dimension * spatial_dimension; - initInternalVector(this->ghost_stress_viscosity, stress_size, "stress_viscosity", _ghost); - initInternalVector(this->stress_viscosity , stress_size, "stress_viscosity"); - initInternalVector(this->ghost_stress_elastic , stress_size, "stress_elastic", _ghost); - initInternalVector(this->stress_elastic , stress_size, "stress_elastic"); + initInternalVector(this->stress_viscosity, stress_size, "stress_viscosity"); + initInternalVector(this->stress_elastic , stress_size, "stress_elastic"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElasticCaughey::initMaterial() { AKANTU_DEBUG_IN(); MaterialElastic::initMaterial(); - resizeInternalVector(this->ghost_stress_viscosity); - resizeInternalVector(this->stress_viscosity ); - resizeInternalVector(this->ghost_stress_elastic ); - resizeInternalVector(this->stress_elastic ); + resizeInternalVector(this->stress_viscosity); + resizeInternalVector(this->stress_elastic ); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElasticCaughey::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); UInt spatial_dimension = model->getSpatialDimension(); - Vector * elem_filter; - Vector * stress_visc; - Vector * stress_el ; - if(ghost_type == _not_ghost) { - elem_filter = element_filter[el_type]; - stress_visc = stress_viscosity[el_type]; - stress_el = stress_elastic [el_type]; - } else { - elem_filter = ghost_element_filter[el_type]; - stress_visc = ghost_stress_viscosity[el_type]; - stress_el = ghost_stress_elastic [el_type]; - } + Vector * elem_filter = element_filter (el_type, ghost_type); + Vector * stress_visc = stress_viscosity(el_type, ghost_type); + Vector * stress_el = stress_elastic (el_type, ghost_type); MaterialElastic::computeStress(el_type, ghost_type); Vector & velocity = model->getVelocity(); - Vector strain_rate(0, spatial_dimension * spatial_dimension); + Vector strain_rate(0, spatial_dimension * spatial_dimension, "strain_rate"); model->getFEM().gradientOnQuadraturePoints(velocity, strain_rate, spatial_dimension, el_type, ghost_type, elem_filter); Real F[3*3]; Real sigma[3*3]; Real * strain_rate_val = strain_rate.values; Real * stress_visc_val = stress_visc->values; Real * stress_el_val = stress_el->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_rate_val[spatial_dimension * i + j]; MaterialElastic::computeStress(F, sigma); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) { - stress_visc_val[spatial_dimension*i + j] = alpha * sigma[3 * i + j]; - stress_el_val [spatial_dimension*i + j] = stress_val[spatial_dimension*i + j]; - stress_val [spatial_dimension*i + j] += stress_visc_val[spatial_dimension*i + j]; + stress_visc_val[spatial_dimension * i + j] = alpha * sigma[3 * i + j]; + stress_el_val [spatial_dimension * i + j] = stress_val[spatial_dimension*i + j]; + stress_val [spatial_dimension * i + j] += stress_visc_val[spatial_dimension*i + j]; } + strain_rate_val += spatial_dimension * spatial_dimension; stress_visc_val += spatial_dimension * spatial_dimension; stress_el_val += spatial_dimension * spatial_dimension; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElasticCaughey::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); - Vector * stress_el; - if(ghost_type == _not_ghost) { - stress_el = stress_elastic[el_type]; - } else { - stress_el = ghost_stress_elastic[el_type]; - } + if(ghost_type != _not_ghost) return; + + Vector * stress_el = stress_elastic(el_type, ghost_type); Real * stress_el_val = stress_el->values; - if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; + Real * epot = potential_energy(el_type, ghost_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; MaterialElastic::computePotentialEnergy(strain_val, stress_el_val, epot); epot++; stress_el_val += spatial_dimension*spatial_dimension; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialElasticCaughey::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "alpha") { sstr >> alpha; } else { MaterialElastic::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialElasticCaughey::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "MaterialElasticCaughey [" << std::endl; MaterialElastic::printself(stream, indent + 1); stream << space << " + artifical viscous ratio : " << alpha << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_elastic_caughey.hh b/model/solid_mechanics/materials/material_elastic_caughey.hh index ff4e21de0..073c9c91f 100644 --- a/model/solid_mechanics/materials/material_elastic_caughey.hh +++ b/model/solid_mechanics/materials/material_elastic_caughey.hh @@ -1,128 +1,126 @@ /** * @file material_elastic_caughey.hh * @author David Kammer * @author Nicolas Richart * @date Wed May 4 15:16:59 2011 * * @brief Material isotropic viscoelastic (according to the Caughey condition) * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" #include "material_elastic.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_ELASTIC_CAUGHEY_HH__ #define __AKANTU_MATERIAL_ELASTIC_CAUGHEY_HH__ __BEGIN_AKANTU__ /** * Material viscoelastic (caughey condition) isotropic * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) - * - Plain_Stress : if 0: plain strain, else: plain stress (default: 0) + * - Plane_Stress : if 0: plane strain, else: plane stress (default: 0) * - alpha : viscous ratio */ class MaterialElasticCaughey : public MaterialElastic { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialElasticCaughey(Model & model, const MaterialID & id = ""); virtual ~MaterialElasticCaughey() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for all elements virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; protected: /// constitutive law for a given quadrature point //inline void computeStress(Real * F, Real * sigma); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(StressViscosity, stress_viscosity, const Vector &); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(StressElastic, stress_elastic, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressViscosity, stress_viscosity, Real); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(StressElastic, stress_elastic, Real); AKANTU_GET_MACRO(Alpha, alpha, const Real&); AKANTU_SET_MACRO(Alpha, alpha, Real &); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// stress due to viscosity - ByElementTypeReal ghost_stress_viscosity; ByElementTypeReal stress_viscosity; /// stress due to elasticity - ByElementTypeReal ghost_stress_elastic; - ByElementTypeReal stress_elastic; + ByElementTypeReal stress_elastic; /// viscous ratio Real alpha; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ //#include "material_elastic_caughey_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator /* inline std::ostream & operator <<(std::ostream & stream, const MaterialElasticCaughey & _this) { _this.printself(stream); return stream; } */ __END_AKANTU__ #endif /* __AKANTU_MATERIAL_ELASTIC_CAUGHEY_HH__ */ diff --git a/model/solid_mechanics/materials/material_elastic_inline_impl.cc b/model/solid_mechanics/materials/material_elastic_inline_impl.cc index bf6adc99c..51082da58 100644 --- a/model/solid_mechanics/materials/material_elastic_inline_impl.cc +++ b/model/solid_mechanics/materials/material_elastic_inline_impl.cc @@ -1,119 +1,109 @@ /** * @file material_elastic_inline_impl.cc * @author Nicolas Richart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material elastic * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline void MaterialElastic::computeStress(Real * F, Real * sigma) { Real trace = F[0] + F[4] + F[8]; /// \F_{11} + \F_{22} + \F_{33} /// \sigma_{ij} = \lamda * \F_{kk} * \delta_{ij} + 2 * \mu * \F_{ij} sigma[0] = lambda * trace + 2*mu*F[0]; sigma[4] = lambda * trace + 2*mu*F[4]; sigma[8] = lambda * trace + 2*mu*F[8]; sigma[1] = sigma[3] = mu * (F[1] + F[3]); sigma[2] = sigma[6] = mu * (F[2] + F[6]); sigma[5] = sigma[7] = mu * (F[5] + F[7]); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computeTangentStiffnessByDim(__attribute__((unused)) akantu::ElementType, akantu::Vector& tangent_matrix, __attribute__((unused)) akantu::GhostType) { AKANTU_DEBUG_IN(); Real * tangent_val = tangent_matrix.values; UInt offset_tangent = tangent_matrix.getNbComponent(); UInt nb_quads = tangent_matrix.getSize(); if (nb_quads == 0) return; memset(tangent_val, 0, offset_tangent * nb_quads * sizeof(Real)); for (UInt q = 0; q < nb_quads; ++q, tangent_val += offset_tangent) { computeTangentStiffness(tangent_val); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ template void MaterialElastic::computeTangentStiffness(Real * tangent) { UInt n = (dim * (dim - 1) / 2 + dim); Real Ep = E/((1+nu)*(1-2*nu)); Real Miiii = Ep * (1-nu); Real Miijj = Ep * nu; Real Mijij = Ep * (1-2*nu) * .5; tangent[0 * n + 0] = Miiii; // test of dimension should by optimized out by the compiler due to the template if(dim >= 2) { tangent[1 * n + 1] = Miiii; tangent[0 * n + 1] = Miijj; tangent[1 * n + 0] = Miijj; tangent[(n - 1) * n + (n - 1)] = Mijij; } if(dim == 3) { tangent[2 * n + 2] = Miiii; tangent[0 * n + 2] = Miijj; tangent[1 * n + 2] = Miijj; tangent[2 * n + 0] = Miijj; tangent[2 * n + 1] = Miijj; tangent[3 * n + 3] = Mijij; tangent[4 * n + 4] = Mijij; } } -/* -------------------------------------------------------------------------- */ -inline void MaterialElastic::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { - *epot = 0.; - for (UInt i = 0, t = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j, ++t) - (*epot) += sigma[t] * F[t] ; - - *epot *= .5; -} - /* -------------------------------------------------------------------------- */ inline Real MaterialElastic::celerity() { return sqrt(E/rho); } /* -------------------------------------------------------------------------- */ inline Real MaterialElastic::getStableTimeStep(Real h, __attribute__ ((unused)) const Element & element) { return (h/celerity()); } diff --git a/model/solid_mechanics/materials/material_mazars.cc b/model/solid_mechanics/materials/material_mazars.cc index 2f0de3d8e..5206d1489 100644 --- a/model/solid_mechanics/materials/material_mazars.cc +++ b/model/solid_mechanics/materials/material_mazars.cc @@ -1,164 +1,132 @@ /** * @file material_mazars.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the damage material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material_mazars.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialMazars::MaterialMazars(Model & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; K0 = 1e-4; At = 0.8; Ac = 1.4; Bc= 1900; Bt = 12000; beta = 1.06; - initInternalVector(this->ghost_damage,1,"damage",_ghost); - initInternalVector(this->damage,1,"damage"); + + initInternalVector(this->damage, 1, "damage"); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialMazars::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); - lambda = nu * E / ((1 + nu) * (1 - 2*nu)); - mu = E / (2 * (1 + nu)); - kpa = lambda + 2./3. * mu; resizeInternalVector(this->damage); - resizeInternalVector(this->ghost_damage,_ghost); + is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialMazars::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; - Real * dam ; - if(ghost_type==_ghost) - dam=ghost_damage[el_type]->values; - else - dam= damage[el_type]->values; + Real * dam = damage(el_type, ghost_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; - // for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; - - computeStress(F, sigma,*dam); + computeStress(F, sigma, *dam); ++dam; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -void MaterialMazars::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { - AKANTU_DEBUG_IN(); - - if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; - - computePotentialEnergy(strain_val, stress_val, epot); - epot++; - - MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; - - AKANTU_DEBUG_OUT(); -} - - /* -------------------------------------------------------------------------- */ void MaterialMazars::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "rho") { sstr >> rho; } else if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } else if(key == "K0") { sstr >> K0; } - else if(key == "At") { sstr >> At; } + else if(key == "At") { sstr >> At; } else if(key == "Bt") { sstr >> Bt; } else if(key == "Ac") { sstr >> Ac; } else if(key == "Bc") { sstr >> Bc; } else if(key == "beta") { sstr >> beta; } else { Material::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void MaterialMazars::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_mazars> [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; stream << space << " + K0 : " << K0 << std::endl; stream << space << " + At : " << At << std::endl; stream << space << " + Bt : " << Bt << std::endl; stream << space << " + Ac : " << Ac << std::endl; stream << space << " + Bc : " << Bc << std::endl; - stream << space << " + beta : " << beta << std::endl; - if(is_init) { - stream << space << " + First Lamé coefficient : " << lambda << std::endl; - stream << space << " + Second Lamé coefficient : " << mu << std::endl; - stream << space << " + Bulk coefficient : " << kpa << std::endl; - } + stream << space << " + beta : " << beta << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_mazars.hh b/model/solid_mechanics/materials/material_mazars.hh index 0a6fc62a2..115ab9e92 100644 --- a/model/solid_mechanics/materials/material_mazars.hh +++ b/model/solid_mechanics/materials/material_mazars.hh @@ -1,153 +1,143 @@ /** * @file material_damage.hh * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_MAZARS_HH__ #define __AKANTU_MATERIAL_MAZARS_HH__ __BEGIN_AKANTU__ +/** + * Material Mazars + * + * parameters in the material files : + * - rho : density (default: 0) + * - E : Young's modulus (default: 0) + * - nu : Poisson's ratio (default: 1/2) + * - K0 : Damage threshold + * - At : Parameter damage traction 1 + * - Bt : Parameter damage traction 2 + * - Ac : Parameter damage compression 1 + * - Bc : Parameter damage compression 2 + * - beta : Parameter for shear + */ class MaterialMazars : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialMazars(Model & model, const MaterialID & id = ""); virtual ~MaterialMazars() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma,Real & damage); - /// compute the potential energy for all elements - void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); - - /// compute the potential energy for on element - inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); - /// Compute the tangent stiffness matrix for implicit for a given type void computeTangentStiffness(__attribute__ ((unused)) const ElementType & type, __attribute__ ((unused)) Vector & tangent_matrix, __attribute__ ((unused)) GhostType ghost_type = _not_ghost) { AKANTU_DEBUG_TO_IMPLEMENT(); }; - + /// compute the celerity of wave in the material inline Real celerity(); + inline Real getStableTimeStep(Real h, const Element & element); + /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: - /// get the stable time step - inline Real getStableTimeStep(Real h, const Element & element); - - /// return damage value - ByElementTypeReal & getDamage(){return damage;}; + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ - - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Damage, damage, const Vector &); private: - /// the young modulus Real E; - /// Poisson coefficient Real nu; - /// First Lamé coefficient - Real lambda; - - /// Second Lamé coefficient (shear modulus) - Real mu; - - - /// damage threshold + /// damage threshold Real K0; - ///parameter damage traction 1 + ///parameter damage traction 1 Real At ; - ///parameter damage traction 2 - Real Bt ; - ///parameter damage compression 1 + ///parameter damage traction 2 + Real Bt ; + ///parameter damage compression 1 Real Ac ; - ///parameter damage compression 2 - Real Bc ; + ///parameter damage compression 2 + Real Bc ; ///parameter for shear Real beta ; - - /// Bulk modulus - Real kpa; - /// damage internal variable ByElementTypeReal damage; - ByElementTypeReal ghost_damage; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_mazars_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialMazars & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_MAZARS_HH__ */ diff --git a/model/solid_mechanics/materials/material_mazars_inline_impl.cc b/model/solid_mechanics/materials/material_mazars_inline_impl.cc index c4d5de72c..57dbb71e3 100644 --- a/model/solid_mechanics/materials/material_mazars_inline_impl.cc +++ b/model/solid_mechanics/materials/material_mazars_inline_impl.cc @@ -1,131 +1,118 @@ /** * @file material_mazars_inline_impl.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material damage * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ inline void MaterialMazars::computeStress(Real * F, Real * sigma, Real & dam) { - Real trace = F[0] + F[4] + F[8]; + Real trace = F[0] + F[4] + F[8]; + Real K = 1./3. * (E/(1. - 2.*nu)); + Real G = E / (2*(1 + nu)); + Real lambda = nu * E / ((1 + nu) * (1 - 2*nu)); - /// @f$ \sigma_{ij} = \lambda * F_{kk} * \delta_{ij} + 2 * \mu * F_{ij} @f$ - Real K = 1./3.*(E/(1.-2.*nu)); - Real G = E/(2*(1+nu)); Real Fdiag[3]; Real Fdiagp[3]; - Math::matrix33_eigenvalues(F,Fdiag); + Math::matrix33_eigenvalues(F, Fdiag); + + Fdiagp[0] = std::max(0., Fdiag[0]); + Fdiagp[1] = std::max(0., Fdiag[1]); + Fdiagp[2] = std::max(0., Fdiag[2]); - Fdiagp[0] = std::max(0.,Fdiag[0]); - Fdiagp[1] = std::max(0.,Fdiag[1]); - Fdiagp[2] = std::max(0.,Fdiag[2]); - Real Ehat=sqrt(Fdiagp[0]*Fdiagp[0]+Fdiagp[1]*Fdiagp[1]+Fdiagp[2]*Fdiagp[2]); sigma[0] = K * trace + 2*G * (F[0] - trace/3); sigma[4] = K * trace + 2*G * (F[4] - trace/3); sigma[8] = K * trace + 2*G * (F[8] - trace/3); sigma[1] = sigma[3] = G * (F[1] + F[3]); sigma[2] = sigma[6] = G * (F[2] + F[6]); sigma[5] = sigma[7] = G * (F[5] + F[7]); - - Real Fs = Ehat-K0; - Real damt ; - Real damc ; - if (Fs > 0) { - damt = 1-K0*(1-At)/Ehat-At*(exp(-Bt*(Ehat-K0))); - damc = 1-K0*(1-Ac)/Ehat-Ac*(exp(-Bc*(Ehat-K0))); - Real Cdiag ; + Real Fs = Ehat - K0; + if (Fs > 0.) { + Real damt; + Real damc; + damt = 1 - K0*(1 - At)/Ehat - At*(exp(-Bt*(Ehat - K0))); + damc = 1 - K0*(1 - Ac)/Ehat - Ac*(exp(-Bc*(Ehat - K0))); + + Real Cdiag; Cdiag = E*(1-nu)/((1+nu)*(1-2*nu)); - + Real SigDiag[3]; - SigDiag[0] = Cdiag*Fdiag[0] + lambda*(Fdiag[1]+Fdiag[2]); - SigDiag[1] = Cdiag*Fdiag[1] + lambda*(Fdiag[0]+Fdiag[2]); - SigDiag[2] = Cdiag*Fdiag[2] + lambda*(Fdiag[1]+Fdiag[0]); + SigDiag[0] = Cdiag*Fdiag[0] + lambda*(Fdiag[1] + Fdiag[2]); + SigDiag[1] = Cdiag*Fdiag[1] + lambda*(Fdiag[0] + Fdiag[2]); + SigDiag[2] = Cdiag*Fdiag[2] + lambda*(Fdiag[1] + Fdiag[0]); + Real SigDiagT[3]; - //Real SigDiagC[3]; - for (UInt i = 0; i<3;i++){ - if( SigDiag[i]>=0.){ - SigDiagT[i]= SigDiag[i]; - // SigDiagC[i]=0.; + for (UInt i = 0; i < 3; i++) { + if(SigDiag[i] >= 0.) { + SigDiagT[i] = SigDiag[i]; } else { - // SigDiagC[i]= SigDiag[i]; - SigDiagT[i]=0.; - } + SigDiagT[i] = 0.; + } } - Real TraSigT;//, TraSigC; - TraSigT =SigDiagT[0]+ SigDiagT[1]+SigDiagT[2]; - // TraSigC =SigDiagC[0]+ SigDiagC[1]+SigDiagC[2]; - Real FDiagT [3]; - for (UInt i = 0; i<3;i++){ - FDiagT [i]= (SigDiagT[i]*(1+nu)-TraSigT*nu)/E; + + Real TraSigT; + TraSigT = SigDiagT[0] + SigDiagT[1] + SigDiagT[2]; + + Real FDiagT[3]; + for (UInt i = 0; i < 3; i++){ + FDiagT [i]= (SigDiagT[i]*(1 + nu) - TraSigT*nu)/E; } - Real alphat ; - Real alphac ; + + Real alphat; + alphat = (FDiagT[0]*Fdiagp[0] + FDiagT[1]*Fdiagp[1] + FDiagT[2]*Fdiagp[2])/(Ehat*Ehat); + alphat = std::min(alphat, 1.); + + Real alphac; + alphac = 1 - alphat; + Real damtemp; - alphat= (FDiagT[0]*Fdiagp[0]+FDiagT[1]*Fdiagp[1]+FDiagT[2]*Fdiagp[2])/(Ehat*Ehat); - alphat=std::min(alphat,1.); - alphac = 1-alphat; - damtemp= pow(alphat,beta)*damt+pow(alphac,beta)*damc; - dam=std::max(damtemp,dam); + damtemp = pow(alphat,beta)*damt + pow(alphac,beta)*damc; + + dam = std::max(damtemp, dam); } - dam = std::min(dam,1.); - sigma[0] *= 1-dam; - sigma[4] *= 1-dam; - sigma[8] *= 1-dam; - sigma[1] *= 1-dam; - sigma[3] *= 1-dam; - sigma[2] *= 1-dam; - sigma[6] *= 1-dam; - sigma[5] *= 1-dam; - sigma[7] *= 1-dam; -} + dam = std::min(dam,1.); -/* -------------------------------------------------------------------------- */ -inline void MaterialMazars::computePotentialEnergy(Real * F, Real * sigma, Real * epot) { - *epot = 0.; - for (UInt i = 0, t = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j, ++t) - *epot += sigma[t] * F[t] ; - *epot *= .5; + for(UInt i = 0; i < 9; ++i) sigma[i] *= 1 - dam; } /* -------------------------------------------------------------------------- */ inline Real MaterialMazars::celerity() { return sqrt(E/rho); } /* -------------------------------------------------------------------------- */ -inline Real MaterialMazars::getStableTimeStep(Real h, +inline Real MaterialMazars::getStableTimeStep(Real h, __attribute__ ((unused)) const Element & element) { return (h/celerity()); } diff --git a/model/solid_mechanics/materials/material_neohookean.cc b/model/solid_mechanics/materials/material_neohookean.cc index df2d0ac24..c6869bba1 100644 --- a/model/solid_mechanics/materials/material_neohookean.cc +++ b/model/solid_mechanics/materials/material_neohookean.cc @@ -1,226 +1,236 @@ /** * @file material_neohookean.cc * @author Nicolas Richart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the elastic material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "material_neohookean.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ MaterialNeohookean::MaterialNeohookean(Model & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; - plain_stress = false; + plane_stress = false; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialNeohookean::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); - - if(plain_stress) + if(plane_stress) lambda = 2 * lambda * mu / (lambda + 2 * mu); - kpa = lambda + 2./3. * mu; - is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialNeohookean::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; - for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] += 1; + for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] += 1; //F is now the real F !! computeStress(F, sigma); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void MaterialNeohookean::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; + Real * epot = potential_energy(el_type, ghost_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; computePotentialEnergy(strain_val, epot); epot++; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */ -void MaterialNeohookean::setParam(const std::string & key, const std::string & value, - const MaterialID & id) { - std::stringstream sstr(value); - if(key == "rho") { sstr >> rho; } - else if(key == "E") { sstr >> E; } - else if(key == "nu") { sstr >> nu; } - else if(key == "Plain_Stress") { sstr >> plain_stress; } - else { Material::setParam(key, value, id); } -} - /* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeTangentStiffnessByDim(ElementType el_type, Vector& tangent_matrix, GhostType ghost_type) { AKANTU_DEBUG_IN(); tangent_matrix.clear(); Real F[3*3]; MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_BEGIN(tangent_matrix); memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; - for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] += 1; + for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] += 1; //F is now the real F !! - computeTangentStiffness(tangent_val, F); - MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; + computeTangentStiffness(tangent_val, F); + MATERIAL_TANGENT_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } -/* -------------------------------------------------------------------------- */Real MaterialNeohookean::celerity(const Element & elem ) { - UInt nb_quadrature_points = model->getFEM().getNbQuadraturePoints(elem.type); +/* -------------------------------------------------------------------------- */ +Real MaterialNeohookean::celerity(const Element & elem) { + UInt nb_quadrature_points = + model->getFEM().getNbQuadraturePoints(elem.type, elem.ghost_type); + UInt size_strain = spatial_dimension * spatial_dimension; - - Real *strain_val = strain[elem.type]->values + elem.element * nb_quadrature_points * size_strain; + + Real *strain_val = strain(elem.type, elem.ghost_type)->values + + elem.element * nb_quadrature_points * size_strain; + Real F[3*3]; + Real temprhot = 0; + Real C[3*3], Cinv[3*3], + detC, defvol, + p, + traceCinv, + coef, rhot; - //F is now the real F !! - Real temprhot =0 ; - Real C[3*3], Cinv[3*3],detC, defvol, p, traceCinv, coef,rhot; for (UInt q = 0; q < nb_quadrature_points; ++q) { memset(F,0.,3*3*sizeof(Real)); - for (UInt i = 0; i < spatial_dimension; ++i) - for (UInt j = 0; j < spatial_dimension; ++j) - F[3*i + j] = strain_val[spatial_dimension * i + j]; - for (UInt i = 0; i < spatial_dimension; ++i) - {F[i*3 + i] += 1;} - Math::matMul(3,3,3,1.,F,F,0.,C); - Math::inv3(C,Cinv); - detC=Math::det3(C); - defvol= 0.5*log(detC); - p = lambda*defvol; - traceCinv = Cinv[0]+Cinv[4]+Cinv[8]; - coef=mu-p; + + for (UInt i = 0; i < spatial_dimension; ++i) + for (UInt j = 0; j < spatial_dimension; ++j) + F[3*i + j] = strain_val[spatial_dimension * i + j]; + for (UInt i = 0; i < spatial_dimension; ++i) + F[i*3 + i] += 1; + + Math::matMul(3, 3, 3, 1., F, F, 0., C); + Math::inv3(C, Cinv); + detC = Math::det3(C); + defvol = 0.5*log(detC); + p = lambda*defvol; + traceCinv = Cinv[0] + Cinv[4] + Cinv[8]; + coef = mu - p; + rhot = rho/sqrt(detC); - rhot=std::max(temprhot,rhot); + rhot = std::max(temprhot,rhot); + strain_val += size_strain; } - Real cele = sqrt((lambda+2*coef)*traceCinv*traceCinv/rhot) ; - return cele ; + + Real cele = sqrt((lambda + 2*coef)*traceCinv*traceCinv/rhot) ; + + return cele; } +/* -------------------------------------------------------------------------- */ +void MaterialNeohookean::setParam(const std::string & key, const std::string & value, + const MaterialID & id) { + std::stringstream sstr(value); + if(key == "rho") { sstr >> rho; } + else if(key == "E") { sstr >> E; } + else if(key == "nu") { sstr >> nu; } + else if(key == "Plane_Stress") { sstr >> plane_stress; } + else { Material::setParam(key, value, id); } +} /* -------------------------------------------------------------------------- */ void MaterialNeohookean::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); - stream << space << "Material<_neohookean> [" << std::endl; - if(!plain_stress) - stream << space << " + Plain strain" << std::endl; + stream << space << "MaterialNeohookean [" << std::endl; + if(!plane_stress) + stream << space << " + Plane strain" << std::endl; else - stream << space << " + Plain stress" << std::endl; + stream << space << " + Plane stress" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; if(is_init) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ template -void MaterialNeohookean::computeTangentStiffnessByDim<1>( akantu::ElementType el_type, - akantu::Vector& tangent_matrix, - akantu::GhostType ghost_type); +void MaterialNeohookean::computeTangentStiffnessByDim<1>(akantu::ElementType el_type, + akantu::Vector& tangent_matrix, + akantu::GhostType ghost_type); template - void MaterialNeohookean::computeTangentStiffnessByDim<2>( akantu::ElementType el_type, - akantu::Vector& tangent_matrix, - akantu::GhostType ghost_type); +void MaterialNeohookean::computeTangentStiffnessByDim<2>(akantu::ElementType el_type, + akantu::Vector& tangent_matrix, + akantu::GhostType ghost_type); template - void MaterialNeohookean::computeTangentStiffnessByDim<3>( akantu::ElementType el_type, - akantu::Vector& tangent_matrix, - akantu::GhostType ghost_type); +void MaterialNeohookean::computeTangentStiffnessByDim<3>(akantu::ElementType el_type, + akantu::Vector& tangent_matrix, + akantu::GhostType ghost_type); /* -------------------------------------------------------------------------- */ void MaterialNeohookean::computeTangentStiffness(const ElementType & el_type, - Vector & tangent_matrix, - GhostType ghost_type) { + Vector & tangent_matrix, + GhostType ghost_type) { switch(spatial_dimension) { case 1: { computeTangentStiffnessByDim<1>(el_type, tangent_matrix, ghost_type); break; } case 2: { computeTangentStiffnessByDim<2>(el_type, tangent_matrix, ghost_type); break; } case 3: { computeTangentStiffnessByDim<3>(el_type, tangent_matrix, ghost_type); break; } } } __END_AKANTU__ diff --git a/model/solid_mechanics/materials/material_neohookean.hh b/model/solid_mechanics/materials/material_neohookean.hh index ca834d7c9..b977e958f 100644 --- a/model/solid_mechanics/materials/material_neohookean.hh +++ b/model/solid_mechanics/materials/material_neohookean.hh @@ -1,147 +1,146 @@ /** * @file material_neohookean.hh * @author Nicolas Richart * @date Thu Jul 29 15:00:59 2010 * - * @brief Material isotropic elastic + * @brief Material Neo Hookean * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_MATERIAL_NEOHOOKEAN_HH__ #define __AKANTU_MATERIAL_NEOHOOKEAN_HH__ __BEGIN_AKANTU__ /** * Material elastic isotropic * * parameters in the material files : * - rho : density (default: 0) * - E : Young's modulus (default: 0) * - nu : Poisson's ratio (default: 1/2) * - Plain_Stress : if 0: plain strain, else: plain stress (default: 0) */ class MaterialNeohookean : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: MaterialNeohookean(Model & model, const MaterialID & id = ""); virtual ~MaterialNeohookean() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the tangent stiffness matrix for an element type void computeTangentStiffness(const ElementType & el_type, Vector & tangent_matrix, GhostType ghost_type = _not_ghost); /// compute the potential energy for all elements - void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); - + virtual void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; private: /// compute the celerity of wave in the material Real celerity(const Element & element); /// compute the potential energy for on element inline void computePotentialEnergy(Real * F, Real * epot); protected: /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma); // /// compute the tangent stiffness matrix for an element type template void computeTangentStiffnessByDim(akantu::ElementType, akantu::Vector& tangent_matrix, akantu::GhostType); // /// compute the tangent stiffness matrix for an element template - void computeTangentStiffness( Real * tangent, Real * F); + void computeTangentStiffness(Real * tangent, Real * F); /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h, const Element & element); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// Bulk modulus Real kpa; /// Plain stress or plain strain - bool plain_stress; + bool plane_stress; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "material_neohookean_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const MaterialNeohookean & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_MATERIAL_NEOHOOKEAN_HH__ */ diff --git a/model/solid_mechanics/materials/material_neohookean_inline_impl.cc b/model/solid_mechanics/materials/material_neohookean_inline_impl.cc index 7ef454d6b..ca208bb44 100644 --- a/model/solid_mechanics/materials/material_neohookean_inline_impl.cc +++ b/model/solid_mechanics/materials/material_neohookean_inline_impl.cc @@ -1,118 +1,127 @@ /** * @file material_neohookean_inline_impl.cc * @author Marion Chambart * @date Tue Jul 27 11:57:43 2010 * * @brief Implementation of the inline functions of the material neohookean * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_math.hh" + /* -------------------------------------------------------------------------- */ inline void MaterialNeohookean::computeStress(Real * F, Real * sigma) { - ///First compute the Left Cauchy-Green deformation tensor : C= F^tF. - Real C[3*3]; - Real S[3*3]; - - UInt i; + ///First compute the Left Cauchy-Green deformation tensor : C= F^tF. + Real C[3*3]; Math::matMul(3,3,3,1.,F,F,0.,C); + ///Compute determinant of C Real detC; detC=Math::det3(C); + Real defvol ; defvol= 0.5*log(detC); + Real p; p = lambda*defvol; + Real traceC; traceC = C[0]+C[4]+C[8]; + Real Cinv[3*3]; - Math::inv3(C,Cinv); - Real coef = p -mu ; - for(i=0;i<3*3;i++){ - S[i]=coef*Cinv[i]; -} - + Math::inv3(C, Cinv); + + Real coef = p - mu; + + Real S[3*3]; + for(UInt i=0; i < 3*3; i++){ + S[i] = coef*Cinv[i]; + } + S[0] = S[0] + mu; S[4] = S[4] + mu; S[8] = S[8] + mu; - Math::matrix_matrix(3, 3,3, F, S, sigma, 1.);} -/* -------------------------------------------------------------------------- */ + Math::matrix_matrix(3, 3,3, F, S, sigma, 1.); +} +/* -------------------------------------------------------------------------- */ template void MaterialNeohookean::computeTangentStiffness(Real * tangent, Real * F ) { UInt n = (dim * (dim - 1) / 2 + dim); Real J = Math::det3(F); - Real alpha = mu-0.5*lambda*(J*J-1); + Real alpha = mu - 0.5*lambda*(J*J - 1); Real Miiii = 2*mu+lambda; Real Miijj = lambda*J*J; Real Mijij = alpha; tangent[0 * n + 0] = Miiii; // test of dimension should by optimized out by the compiler due to the template if(dim >= 2) { tangent[1 * n + 1] = Miiii; tangent[0 * n + 1] = Miijj; tangent[1 * n + 0] = Miijj; tangent[(n - 1) * n + (n - 1)] = Mijij; } if(dim == 3) { tangent[2 * n + 2] = Miiii; tangent[0 * n + 2] = Miijj; tangent[1 * n + 2] = Miijj; tangent[2 * n + 0] = Miijj; tangent[2 * n + 1] = Miijj; tangent[3 * n + 3] = Mijij; tangent[4 * n + 4] = Mijij; } } /* -------------------------------------------------------------------------- */ inline void MaterialNeohookean::computePotentialEnergy(Real * F, Real * epot) { *epot = 0.; Real C[3*3]; Math::matMul(3,3,3,1.,F,F,0.,C); + ///Compute determinant of C Real detC; - detC=Math::det3(C); + detC = Math::det3(C); + Real defvol ; - defvol= 0.5*log(detC); + defvol = 0.5*log(detC); + Real p; p = lambda*defvol; - Real traceC; - traceC = C[0]+C[4]+C[8]; - ///energie potentielle - - *epot = (0.5*p-mu)*defvol+0.5*mu*(traceC-3.); + Real traceC; + traceC = C[0] + C[4] + C[8]; + ///energie potentielle + *epot = (0.5*p - mu)*defvol + 0.5*mu*(traceC - 3.); } /* -------------------------------------------------------------------------- */ -inline Real MaterialNeohookean::getStableTimeStep(Real h, +inline Real MaterialNeohookean::getStableTimeStep(Real h, const Element & element) { return (h/celerity(element)); } diff --git a/model/solid_mechanics/solid_mechanics_model.cc b/model/solid_mechanics/solid_mechanics_model.cc index 5e634b59b..cc5b9ce8d 100644 --- a/model/solid_mechanics/solid_mechanics_model.cc +++ b/model/solid_mechanics/solid_mechanics_model.cc @@ -1,863 +1,865 @@ /** * @file solid_mechanics_model.cc * @author Nicolas Richart * @date Thu Jul 22 14:35:38 2010 * * @brief Implementation of the SolidMechanicsModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "aka_math.hh" #include "integration_scheme_2nd_order.hh" #include "static_communicator.hh" #include "sparse_matrix.hh" #include "solver.hh" #include "dof_synchronizer.hh" #ifdef AKANTU_USE_MUMPS #include "solver_mumps.hh" #endif /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SolidMechanicsModel::SolidMechanicsModel(Mesh & mesh, UInt dim, const ModelID & id, const MemoryID & memory_id) : Model(id, memory_id), time_step(NAN), f_m2a(1.0), mass_matrix(NULL), velocity_damping_matrix(NULL), stiffness_matrix(NULL),jacobian_matrix(NULL), integrator(NULL), increment_flag(false), solver(NULL), spatial_dimension(dim), mesh(mesh) { AKANTU_DEBUG_IN(); createSynchronizerRegistry(this); if (spatial_dimension == 0) spatial_dimension = mesh.getSpatialDimension(); registerFEMObject("SolidMechanicsFEM", mesh, spatial_dimension); this->displacement = NULL; this->mass = NULL; this->velocity = NULL; this->acceleration = NULL; this->force = NULL; this->residual = NULL; this->boundary = NULL; this->increment = NULL; this->increment_acceleration = NULL; - for(UInt t = _not_defined; t < _max_element_type; ++t) { - this->element_material[t] = NULL; - this->ghost_element_material[t] = NULL; - } - this->dof_synchronizer = NULL; materials.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SolidMechanicsModel::~SolidMechanicsModel() { AKANTU_DEBUG_IN(); std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { delete *mat_it; } materials.clear(); delete integrator; if(solver) delete solver; if(mass_matrix) delete mass_matrix; if(velocity_damping_matrix) delete velocity_damping_matrix; if(stiffness_matrix) delete stiffness_matrix; if(jacobian_matrix) delete jacobian_matrix; if(dof_synchronizer) delete dof_synchronizer; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Initialisation */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initParallel(MeshPartition * partition, DataAccessor * data_accessor) { AKANTU_DEBUG_IN(); if (data_accessor == NULL) data_accessor = this; Synchronizer & synch_parallel = createParallelSynch(partition,data_accessor); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_mass); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_for_strain); synch_registry->registerSynchronizer(synch_parallel,_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initExplicit() { AKANTU_DEBUG_IN(); if (integrator) delete integrator; integrator = new CentralDifference(); // UInt nb_nodes = mesh.getNbNodes(); // std::stringstream sstr_eq; sstr_eq << id << ":equation_number"; // equation_number = &(alloc(sstr_eq.str(), nb_nodes, spatial_dimension, 0)); // Int * equation_number_val = equation_number->values; // for (UInt n = 0; n < nb_nodes; ++n) { // for (UInt d = 0; d < spatial_dimension; ++d) { // UInt eq_num = n * spatial_dimension + d; // *(equation_number_val++) = eq_num; // } // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initVectors() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_disp; sstr_disp << id << ":displacement"; std::stringstream sstr_mass; sstr_mass << id << ":mass"; std::stringstream sstr_velo; sstr_velo << id << ":velocity"; std::stringstream sstr_acce; sstr_acce << id << ":acceleration"; std::stringstream sstr_forc; sstr_forc << id << ":force"; std::stringstream sstr_resi; sstr_resi << id << ":residual"; std::stringstream sstr_boun; sstr_boun << id << ":boundary"; displacement = &(alloc(sstr_disp.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); - mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension)); // \todo see if it must not be spatial_dimension + mass = &(alloc(sstr_mass.str(), nb_nodes, spatial_dimension, 0)); // \todo see if it must not be spatial_dimension velocity = &(alloc(sstr_velo.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); acceleration = &(alloc(sstr_acce.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); force = &(alloc(sstr_forc.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); residual = &(alloc(sstr_resi.str(), nb_nodes, spatial_dimension, REAL_INIT_VALUE)); boundary = &(alloc(sstr_boun.str(), nb_nodes, spatial_dimension, false)); std::stringstream sstr_curp; sstr_curp << id << ":current_position"; current_position = &(alloc(sstr_curp.str(), 0, spatial_dimension, REAL_INIT_VALUE)); - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - UInt nb_element = mesh.getNbElement(*it); - - if(!element_material[*it]) { - std::stringstream sstr_elma; sstr_elma << id << ":element_material:" << *it; - element_material[*it] = &(alloc(sstr_elma.str(), nb_element, 1, 0)); + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + std::string ghost_id = ""; + if (gt == _ghost) { + ghost_id = "ghost_"; } - } - const Mesh::ConnectivityTypeList & ghost_type_list = - mesh.getConnectivityTypeList(_ghost); - - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - UInt nb_element = mesh.getNbElement(*it,_ghost); - - std::stringstream sstr_elma; sstr_elma << id << ":ghost_element_material:" << *it; - ghost_element_material[*it] = &(alloc(sstr_elma.str(), nb_element, 1, 0)); + const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + UInt nb_element = mesh.getNbElement(*it, gt); + if(!element_material.exists(*it, gt)) { + std::stringstream sstr_elma; sstr_elma << id << ":" << ghost_id << "element_material:" << *it; + element_material(*it, gt) = &(alloc(sstr_elma.str(), nb_element, 1, 0)); + } + } } dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initLocalDOFEquationNumbers(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initModel() { /// \todo add the current position as a parameter to initShapeFunctions for /// large deformation getFEM().initShapeFunctions(_not_ghost); - getFEM().initShapeFunctions(_ghost); } + /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initPBC(UInt x, UInt y, UInt z){ Model::initPBC(x,y,z); PBCSynchronizer * synch = new PBCSynchronizer(pbc_pair); - synch_registry->registerSynchronizer(*synch,_gst_smm_uv); - synch_registry->registerSynchronizer(*synch,_gst_smm_mass); - changeLocalEquationNumberforPBC(pbc_pair,mesh.getSpatialDimension()); + synch_registry->registerSynchronizer(*synch, _gst_smm_uv); + synch_registry->registerSynchronizer(*synch, _gst_smm_mass); + changeLocalEquationNumberforPBC(pbc_pair, mesh.getSpatialDimension()); } + /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateCurrentPosition() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); current_position->resize(nb_nodes); //Vector * current_position = new Vector(nb_nodes, spatial_dimension, NAN, "position"); Real * current_position_val = current_position->values; Real * position_val = mesh.getNodes().values; Real * displacement_val = displacement->values; /// compute current_position = initial_position + displacement memcpy(current_position_val, position_val, nb_nodes*spatial_dimension*sizeof(Real)); for (UInt n = 0; n < nb_nodes*spatial_dimension; ++n) { *current_position_val++ += *displacement_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initializeUpdateResidualData() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); residual->resize(nb_nodes); /// copy the forces in residual for boundary conditions memcpy(residual->values, force->values, nb_nodes*spatial_dimension*sizeof(Real)); updateCurrentPosition(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Explicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateResidual(bool need_initialize) { AKANTU_DEBUG_IN(); // f = f_ext - f_int - Ma - Cv // f = f_ext if (need_initialize) initializeUpdateResidualData(); // f -= fint /// start synchronization synch_registry->asynchronousSynchronize(_gst_smm_for_strain); /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { //(*mat_it)->updateResidual(*current_position, _not_ghost); (*mat_it)->updateResidual(*displacement, _not_ghost); } /// finalize communications synch_registry->waitEndSynchronize(_gst_smm_for_strain); /// call update residual on each ghost elements for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { //(*mat_it)->updateResidual(*current_position, _ghost); (*mat_it)->updateResidual(*displacement, _ghost); } - // f -= Ma - if(mass_matrix) { - // if full mass_matrix - Vector * Ma = new Vector(*acceleration, true, "Ma"); - *Ma *= *mass_matrix; - *residual -= *Ma; - delete Ma; - } else { - // else lumped mass - UInt nb_nodes = acceleration->getSize(); - UInt nb_degre_of_freedom = acceleration->getNbComponent(); - - Real * mass_val = mass->values; - Real * accel_val = acceleration->values; - Real * res_val = residual->values; - bool * boundary_val = boundary->values; - - for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n) { - if(!(*boundary_val)) { - *res_val -= *accel_val * *mass_val; - } - boundary_val++; - res_val++; - mass_val++; - accel_val++; - } - } + // // f -= Ma + // if(mass_matrix) { + // // if full mass_matrix + // Vector * Ma = new Vector(*acceleration, true, "Ma"); + // *Ma *= *mass_matrix; + // *residual -= *Ma; + // delete Ma; + // } else { + // // else lumped mass + // UInt nb_nodes = acceleration->getSize(); + // UInt nb_degre_of_freedom = acceleration->getNbComponent(); + + // Real * mass_val = mass->values; + // Real * accel_val = acceleration->values; + // Real * res_val = residual->values; + // bool * boundary_val = boundary->values; + + // for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n) { + // if(!(*boundary_val)) { + // *res_val -= *accel_val * *mass_val; + // } + // boundary_val++; + // res_val++; + // mass_val++; + // accel_val++; + // } + // } - // f -= Cv - if(velocity_damping_matrix) { - Vector * Cv = new Vector(*velocity); - *Cv *= *velocity_damping_matrix; - *residual -= *Cv; - delete Cv; - } + // // f -= Cv + // if(velocity_damping_matrix) { + // Vector * Cv = new Vector(*velocity); + // *Cv *= *velocity_damping_matrix; + // *residual -= *Cv; + // delete Cv; + // } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::updateAcceleration() { AKANTU_DEBUG_IN(); UInt nb_nodes = acceleration->getSize(); UInt nb_degre_of_freedom = acceleration->getNbComponent(); if(!increment_acceleration) increment_acceleration = new Vector(nb_nodes, nb_degre_of_freedom); increment_acceleration->resize(nb_nodes); increment_acceleration->clear(); Real * mass_val = mass->values; Real * residual_val = residual->values; bool * boundary_val = boundary->values; Real * inc = increment_acceleration->values; + Real * accel_val = acceleration->values; for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < nb_degre_of_freedom; d++) { if(!(*boundary_val)) { - *inc = f_m2a * (*residual_val / *mass_val); + *inc = f_m2a * (*residual_val / *mass_val) - *accel_val; } residual_val++; boundary_val++; inc++; mass_val++; + accel_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitPred() { AKANTU_DEBUG_IN(); if(increment_flag) { memcpy(increment->values, displacement->values, displacement->getSize()*displacement->getNbComponent()*sizeof(Real)); } AKANTU_DEBUG_ASSERT(integrator,"itegrator should have been allocated: " << "have called initExplicit ? " << "or initImplicit ?"); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); if(increment_flag) { Real * inc_val = increment->values; Real * dis_val = displacement->values; UInt nb_nodes = displacement->getSize(); for (UInt n = 0; n < nb_nodes; ++n) { *inc_val = *dis_val - *inc_val; inc_val++; dis_val++; } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::explicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrAccel(time_step, *displacement, *velocity, *acceleration, *boundary, *increment_acceleration); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Implicit scheme */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initImplicit(bool dynamic) { AKANTU_DEBUG_IN(); UInt nb_global_node = mesh.getNbGlobalNodes(); std::stringstream sstr; sstr << id << ":stiffness_matrix"; stiffness_matrix = new SparseMatrix(nb_global_node * spatial_dimension, _symmetric, spatial_dimension, sstr.str(), memory_id); // if(!dof_synchronizer) dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); dof_synchronizer->initGlobalDOFEquationNumbers(); stiffness_matrix->buildProfile(mesh, *dof_synchronizer); SparseMatrix * matrix; if(dynamic) { if(integrator) delete integrator; integrator = new TrapezoidalRule2(); std::stringstream sstr_jac; sstr_jac << id << ":jacobian_matrix"; jacobian_matrix = new SparseMatrix(*stiffness_matrix, sstr_jac.str(), memory_id); // jacobian_matrix->buildProfile(mesh, *dof_synchronizer); matrix = jacobian_matrix; } else { matrix = stiffness_matrix; } #ifdef AKANTU_USE_MUMPS std::stringstream sstr_solv; sstr_solv << id << ":solver_stiffness_matrix"; solver = new SolverMumps(*matrix, sstr_solv.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS solver->initialize(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initialAcceleration() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma = f"); Solver * acc_solver = NULL; #ifdef AKANTU_USE_MUMPS std::stringstream sstr; sstr << id << ":solver_mass_matrix"; acc_solver = new SolverMumps(*mass_matrix, sstr.str()); dof_synchronizer->initScatterGatherCommunicationScheme(); #else AKANTU_DEBUG_ERROR("You should at least activate one solver."); #endif //AKANTU_USE_MUMPS acc_solver->initialize(); mass_matrix->applyBoundary(*boundary); acc_solver->setRHS(*residual); acc_solver->solve(*acceleration); delete acc_solver; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleStiffnessMatrix() { AKANTU_DEBUG_IN(); stiffness_matrix->clear(); /// call compute stiffness matrix on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { (*mat_it)->assembleStiffnessMatrix(*displacement, _not_ghost); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveDynamic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ma + Cv + Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); AKANTU_DEBUG_ASSERT(mass_matrix != NULL, "You should first initialize the implicit solver and assemble the mass matrix"); NewmarkBeta * nmb_int = dynamic_cast(integrator); Real c = nmb_int->getAccelerationCoefficient(time_step); Real d = nmb_int->getVelocityCoefficient(time_step); Real e = nmb_int->getDisplacementCoefficient(time_step); // A = c M + d C + e K jacobian_matrix->clear(); jacobian_matrix->add(*stiffness_matrix, e); jacobian_matrix->add(*mass_matrix, c); if(velocity_damping_matrix) jacobian_matrix->add(*velocity_damping_matrix, d); jacobian_matrix->applyBoundary(*boundary); #ifndef AKANTU_NDEBUG if(AKANTU_DEBUG_TEST(dblDump)) jacobian_matrix->saveMatrix("J.mtx"); #endif solver->setRHS(*residual); if(!increment) setIncrementFlagOn(); // solve A w = f solver->solve(*increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::solveStatic() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_INFO("Solving Ku = f"); AKANTU_DEBUG_ASSERT(stiffness_matrix != NULL, "You should first initialize the implicit solver and assemble the stiffness matrix"); UInt nb_nodes = displacement->getSize(); UInt nb_degre_of_freedom = displacement->getNbComponent(); stiffness_matrix->applyBoundary(*boundary); solver->setRHS(*residual); if(!increment) setIncrementFlagOn(); solver->solve(*increment); Real * increment_val = increment->values; Real * displacement_val = displacement->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes * nb_degre_of_freedom; ++n) { if(!(*boundary_val)) { *displacement_val += *increment_val; } displacement_val++; boundary_val++; increment_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance) { Real error; bool tmp = testConvergenceIncrement(tolerance, error); AKANTU_DEBUG_INFO("Norm of increment : " << error); return tmp; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceIncrement(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = displacement->getSize(); UInt nb_degre_of_freedom = displacement->getNbComponent(); norm = 0; Real * increment_val = increment->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt d = 0; d < nb_degre_of_freedom; ++d) { if(!(*boundary_val) && is_local_node) { norm += *increment_val * *increment_val; } boundary_val++; increment_val++; } } StaticCommunicator::getStaticCommunicator()->allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance) { Real error; bool tmp = testConvergenceResidual(tolerance, error); AKANTU_DEBUG_INFO("Norm of residual : " << error); return tmp; } /* -------------------------------------------------------------------------- */ bool SolidMechanicsModel::testConvergenceResidual(Real tolerance, Real & norm) { AKANTU_DEBUG_IN(); UInt nb_nodes = residual->getSize(); norm = 0; Real * residual_val = residual->values; bool * boundary_val = boundary->values; for (UInt n = 0; n < nb_nodes; ++n) { bool is_local_node = mesh.isLocalOrMasterNode(n); if(is_local_node) { for (UInt d = 0; d < spatial_dimension; ++d) { if(!(*boundary_val)) { norm += *residual_val * *residual_val; } boundary_val++; residual_val++; } } else { boundary_val += spatial_dimension; residual_val += spatial_dimension; } } StaticCommunicator::getStaticCommunicator()->allReduce(&norm, 1, _so_sum); norm = sqrt(norm); AKANTU_DEBUG_ASSERT(!isnan(norm), "Something goes wrong in the solve phase"); AKANTU_DEBUG_OUT(); return (norm < tolerance); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitPred() { AKANTU_DEBUG_IN(); integrator->integrationSchemePred(time_step, *displacement, *velocity, *acceleration, *boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::implicitCorr() { AKANTU_DEBUG_IN(); integrator->integrationSchemeCorrDispl(time_step, *displacement, *velocity, *acceleration, *boundary, *increment); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ /* Information */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::synchronizeBoundaries() { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(synch_registry,"Synchronizer registry was not initialized." << " Did you call initParallel ?"); synch_registry->synchronize(_gst_smm_boundary); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::setIncrementFlagOn() { AKANTU_DEBUG_IN(); if(!increment) { UInt nb_nodes = mesh.getNbNodes(); std::stringstream sstr_inc; sstr_inc << id << ":increment"; increment = &(alloc(sstr_inc.str(), nb_nodes, spatial_dimension, 0)); } increment_flag = true; AKANTU_DEBUG_OUT(); } + + /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getStableTimeStep() { AKANTU_DEBUG_IN(); + Real min_dt = getStableTimeStep(_not_ghost); + + /// reduction min over all processors + StaticCommunicator::getStaticCommunicator()->allReduce(&min_dt, 1, _so_min); + + AKANTU_DEBUG_OUT(); + return min_dt; +} + +/* -------------------------------------------------------------------------- */ +Real SolidMechanicsModel::getStableTimeStep(const GhostType & ghost_type) { + AKANTU_DEBUG_IN(); + Material ** mat_val = &(materials.at(0)); Real min_dt = std::numeric_limits::max(); Real * coord = mesh.getNodes().values; Real * disp_val = displacement->values; - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; Element elem; + elem.ghost_type = ghost_type; + + const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(ghost_type); + Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(mesh.getSpatialDimension(*it) != spatial_dimension) continue; elem.type = *it; UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); UInt nb_element = mesh.getNbElement(*it); - UInt * conn = mesh.getConnectivity(*it).values; - UInt * elem_mat_val = element_material[*it]->values; + UInt * conn = mesh.getConnectivity(*it, ghost_type).values; + UInt * elem_mat_val = element_material(*it, ghost_type)->values; + Real * u = new Real[nb_nodes_per_element*spatial_dimension]; for (UInt el = 0; el < nb_element; ++el) { UInt el_offset = el * nb_nodes_per_element; elem.element = el; for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n] * spatial_dimension; memcpy(u + n * spatial_dimension, coord + offset_conn, spatial_dimension * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) { u[n * spatial_dimension + i] += disp_val[offset_conn + i]; } } Real el_size = getFEM().getElementInradius(u, *it); Real el_dt = mat_val[elem_mat_val[el]]->getStableTimeStep(el_size, elem); min_dt = min_dt > el_dt ? el_dt : min_dt; } delete [] u; } - - /// reduction min over all processors - StaticCommunicator::getStaticCommunicator()->allReduce(&min_dt, 1, _so_sum); - - AKANTU_DEBUG_OUT(); return min_dt; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getPotentialEnergy() { AKANTU_DEBUG_IN(); Real epot = 0.; /// call update residual on each local elements std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { epot += (*mat_it)->getPotentialEnergy(); } /// reduction sum over all processors StaticCommunicator::getStaticCommunicator()->allReduce(&epot, 1, _so_sum); AKANTU_DEBUG_OUT(); return epot; } /* -------------------------------------------------------------------------- */ Real SolidMechanicsModel::getKineticEnergy() { AKANTU_DEBUG_IN(); Real ekin = 0.; UInt nb_nodes = mesh.getNbNodes(); Real * vel_val = velocity->values; Real * mass_val = mass->values; for (UInt n = 0; n < nb_nodes; ++n) { - Real v2 = 0; + Real mv2 = 0; bool is_local_node = mesh.isLocalOrMasterNode(n); for (UInt i = 0; i < spatial_dimension; ++i) { - if(is_local_node) { - v2 += *vel_val * *vel_val; - } + // if(is_local_node) { + mv2 += is_local_node * *vel_val * *vel_val * *mass_val; + // } vel_val++; + mass_val++; } - ekin += *mass_val * v2; - mass_val++; + ekin += mv2; } StaticCommunicator::getStaticCommunicator()->allReduce(&ekin, 1, _so_sum); AKANTU_DEBUG_OUT(); return ekin * .5; } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Solid Mechanics Model [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + spatial dimension : " << spatial_dimension << std::endl; stream << space << " + fem [" << std::endl; getFEM().printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + nodals information [" << std::endl; displacement->printself(stream, indent + 2); mass ->printself(stream, indent + 2); velocity ->printself(stream, indent + 2); acceleration->printself(stream, indent + 2); force ->printself(stream, indent + 2); residual ->printself(stream, indent + 2); boundary ->printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << " + connectivity type information [" << std::endl; - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - stream << space << AKANTU_INDENT << AKANTU_INDENT << " + " << *it <<" [" << std::endl; - element_material[*it]->printself(stream, indent + 3); - stream << space << AKANTU_INDENT << AKANTU_INDENT << "]" << std::endl; - } + element_material.printself(stream, indent + 2); stream << space << AKANTU_INDENT << "]" << std::endl; stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model.hh b/model/solid_mechanics/solid_mechanics_model.hh index 5ae1eabd9..5c59520b7 100644 --- a/model/solid_mechanics/solid_mechanics_model.hh +++ b/model/solid_mechanics/solid_mechanics_model.hh @@ -1,445 +1,454 @@ /** * @file solid_mechanics_model.hh * @author Nicolas Richart * @date[creation] Thu Jul 22 11:51:06 2010 * @date[last modification] Thu Oct 14 14:00:06 2010 * * @brief Model of Solid Mechanics * * @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 . * */ /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_SOLID_MECHANICS_MODEL_HH__ #define __AKANTU_SOLID_MECHANICS_MODEL_HH__ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "model.hh" #include "data_accessor.hh" #include "material.hh" #include "integrator_gauss.hh" #include "shape_lagrange.hh" #include "aka_types.hh" /* -------------------------------------------------------------------------- */ namespace akantu { // class Material; class IntegrationScheme2ndOrder; class Contact; class Solver; class SparseMatrix; } __BEGIN_AKANTU__ class SolidMechanicsModel : public Model, public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: typedef FEMTemplate MyFEMType; SolidMechanicsModel(Mesh & mesh, UInt spatial_dimension = 0, const ModelID & id = "solid_mechanics_model", const MemoryID & memory_id = 0); virtual ~SolidMechanicsModel(); /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: /// register the tags associated with the parallel synchronizer void initParallel(MeshPartition * partition, DataAccessor * data_accessor=NULL); /// allocate all vectors void initVectors(); /// initialize all internal arrays for materials void initMaterials(); /// initialize the model void initModel(); /// init PBC synchronizer void initPBC(UInt x,UInt y, UInt z); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* PBC */ /* ------------------------------------------------------------------------ */ public: /// change the equation number for proper assembly when using PBC void changeEquationNumberforPBC(std::map & pbc_pair); /* ------------------------------------------------------------------------ */ /* Explicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the array needed by updateResidual (residual, current_position) void initializeUpdateResidualData(); /// update the current position vector void updateCurrentPosition(); /// assemble the residual for the explicit scheme void updateResidual(bool need_initialize = true); /// compute the acceleration from the residual void updateAcceleration(); /// explicit integration predictor void explicitPred(); /// explicit integration corrector void explicitCorr(); /// initialize the stuff for the explicit scheme void initExplicit(); /* ------------------------------------------------------------------------ */ /* Implicit */ /* ------------------------------------------------------------------------ */ public: /// initialize the stuff for the implicit solver void initImplicit(bool dynamic = false); /// solve Ma = f to get the initial acceleration void initialAcceleration(); /// assemble the stiffness matrix void assembleStiffnessMatrix(); /// solve @f[ A\delta u = f_ext - f_int @f] void solveDynamic(); /// solve Ku = f void solveStatic(); /// test the convergence (norm of increment) bool testConvergenceIncrement(Real tolerance); bool testConvergenceIncrement(Real tolerance, Real & error); /// test the convergence (norm of residual) bool testConvergenceResidual(Real tolerance); bool testConvergenceResidual(Real tolerance, Real & error); /// implicit time integration predictor void implicitPred(); /// implicit time integration corrector void implicitCorr(); /* ------------------------------------------------------------------------ */ /* Boundaries (solid_mechanics_model_boundary.cc) */ /* ------------------------------------------------------------------------ */ public: + /// compute force vector from a function(x,y,z) that describe stresses + void computeForcesFromFunction(BoundaryFunction in_function, + BoundaryFunctionType function_type); + /// integrate a force on the boundary by providing a stress tensor void computeForcesByStressTensor(const Vector & stresses, - const ElementType & type); + const ElementType & type, + const GhostType & ghost_type); /// integrate a force on the boundary by providing a traction vector void computeForcesByTractionVector(const Vector & tractions, - const ElementType & type); - - /// compute force vector from a function(x,y,z) that describe stresses - void computeForcesFromFunction(BoundaryFunction in_function, - BoundaryFunctionType function_type); + const ElementType & type, + const GhostType & ghost_type); /// synchronize the ghost element boundaries values void synchronizeBoundaries(); /* ------------------------------------------------------------------------ */ /* Materials (solid_mechanics_model_material.cc) */ /* ------------------------------------------------------------------------ */ public: /// read the material files to instantiate all the materials void readMaterials(const std::string & filename); /// read a custom material with a keyword and class as template template UInt readCustomMaterial(const std::string & filename, const std::string & keyword); private: /// read properties part of a material file and create the material template Material * readMaterialProperties(std::ifstream & infile, MaterialID mat_id, UInt ¤t_line); /* ------------------------------------------------------------------------ */ /* Mass (solid_mechanics_model_mass.cc) */ /* ------------------------------------------------------------------------ */ public: /// assemble the lumped mass matrix void assembleMassLumped(); /// assemble the mass matrix void assembleMass(); private: /// assemble the lumped mass matrix for local and ghost elements void assembleMassLumped(GhostType ghost_type); void assembleMass(GhostType ghost_type); /// fill a vector of rho void computeRho(Vector & rho, ElementType type, GhostType ghost_type); /* ------------------------------------------------------------------------ */ /* Data Accessor inherited members */ /* ------------------------------------------------------------------------ */ public: inline virtual UInt getNbDataToPack(const Element & element, SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; inline virtual UInt getNbDataToPack(SynchronizationTag tag) const; inline virtual UInt getNbDataToUnpack(SynchronizationTag tag) const; inline virtual void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; inline virtual void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// return the dimension of the system space AKANTU_GET_MACRO(SpatialDimension, spatial_dimension, UInt); /// get the current value of the time step AKANTU_GET_MACRO(TimeStep, time_step, Real); /// set the value of the time step AKANTU_SET_MACRO(TimeStep, time_step, Real); /// get the value of the conversion from forces/ mass to acceleration AKANTU_GET_MACRO(F_M2A, f_m2a, Real); /// set the value of the conversion from forces/ mass to acceleration AKANTU_SET_MACRO(F_M2A, f_m2a, Real); /// get the SolidMechanicsModel::displacement vector AKANTU_GET_MACRO(Displacement, *displacement, Vector &); + /** * @brief get the SolidMechanicsModel::current_position vector \warn only * consistent after a call to SolidMechanicsModel::updateCurrentPosition */ AKANTU_GET_MACRO(CurrentPosition, *current_position, const Vector &); + /** * @brief get the SolidMechanicsModel::increment vector \warn only consistent * if SolidMechanicsModel::setIncrementFlagOn has been called before */ AKANTU_GET_MACRO(Increment, *increment, const Vector &); /// get the lumped SolidMechanicsModel::mass vector AKANTU_GET_MACRO(Mass, *mass, const Vector &); /// get the SolidMechanicsModel::velocity vector AKANTU_GET_MACRO(Velocity, *velocity, Vector &); + /** * @brief get the SolidMechanicsModel::acceleration vector, updated by * SolidMechanicsModel::updateAcceleration */ AKANTU_GET_MACRO(Acceleration, *acceleration, Vector &); + /// get the SolidMechanicsModel::force vector (boundary forces) AKANTU_GET_MACRO(Force, *force, Vector &); + /// get the SolidMechanicsModel::residual vector, computed by SolidMechanicsModel::updateResidual AKANTU_GET_MACRO(Residual, *residual, const Vector &); + /// get the SolidMechanicsModel::boundary vector AKANTU_GET_MACRO(Boundary, *boundary, Vector &); /// get the value of the SolidMechanicsModel::increment_flag AKANTU_GET_MACRO(IncrementFlag, increment_flag, bool); /// get the SolidMechanicsModel::element_material vector corresponding to a given akantu::ElementType - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE(ElementMaterial, element_material, UInt); /// get a particular material inline Material & getMaterial(UInt mat_index); inline const Material & getMaterial(UInt mat_index) const; /// give the number of materials inline UInt getNbMaterials() { return materials.size(); }; /// compute the stable time step Real getStableTimeStep(); /// compute the potential energy Real getPotentialEnergy(); /// compute the kinetic energy Real getKineticEnergy(); /// set the Contact object AKANTU_SET_MACRO(Contact, contact, Contact *); /** * @brief set the SolidMechanicsModel::increment_flag to on, the activate the * update of the SolidMechanicsModel::increment vector */ void setIncrementFlagOn(); /// get the stiffness matrix AKANTU_GET_MACRO(StiffnessMatrix, *stiffness_matrix, SparseMatrix &); /// get the mass matrix AKANTU_GET_MACRO(MassMatrix, *mass_matrix, SparseMatrix &); inline FEM & getFEMBoundary(std::string name = ""); +private: + /// compute the stable time step + Real getStableTimeStep(const GhostType & ghost_type); + /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ private: /// time step Real time_step; /// conversion coefficient form force/mass to acceleration Real f_m2a; /// displacements array Vector * displacement; /// lumped mass array Vector * mass; /// velocities array Vector * velocity; /// accelerations array Vector * acceleration; /// accelerations array Vector * increment_acceleration; /// forces array Vector * force; /// residuals array Vector * residual; /// boundaries array Vector * boundary; /// array of current position used during update residual Vector * current_position; /// mass matrix SparseMatrix * mass_matrix; /// velocity damping matrix SparseMatrix * velocity_damping_matrix; /// stiffness matrix SparseMatrix * stiffness_matrix; /// jacobian matrix @f[A = cM + dD + K@f] with @f[c = \frac{1}{\beta \Delta t^2}, d = \frac{\gamma}{\beta \Delta t} @f] SparseMatrix * jacobian_matrix; /// materials of all elements ByElementTypeUInt element_material; - /// materials of all ghost elements - ByElementTypeUInt ghost_element_material; - /// list of used materials std::vector materials; /// integration scheme of second order used IntegrationScheme2ndOrder * integrator; /// increment of displacement Vector * increment; /// flag defining if the increment must be computed or not bool increment_flag; /// solver for implicit Solver * solver; /// object to resolve the contact Contact * contact; /// the spatial dimension UInt spatial_dimension; /// Mesh Mesh & mesh; }; __END_AKANTU__ /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "parser.hh" __BEGIN_AKANTU__ #include "solid_mechanics_model_inline_impl.cc" /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const SolidMechanicsModel & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_SOLID_MECHANICS_MODEL_HH__ */ diff --git a/model/solid_mechanics/solid_mechanics_model_boundary.cc b/model/solid_mechanics/solid_mechanics_model_boundary.cc index ab8d3ff3f..ffd20cd7d 100644 --- a/model/solid_mechanics/solid_mechanics_model_boundary.cc +++ b/model/solid_mechanics/solid_mechanics_model_boundary.cc @@ -1,207 +1,216 @@ /** * @file solid_mechanics_model_boundary.cc * @author Guillaume ANCIAUX * @date Fri Nov 19 10:23:03 2010 * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "dof_synchronizer.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ /** * @param myf pointer to a function that fills a vector/tensor with respect to * passed coordinates * @param function_type flag to specify the take of function: _bft_stress is * tensor like and _bft_forces is traction like. */ void SolidMechanicsModel::computeForcesFromFunction(BoundaryFunction myf, BoundaryFunctionType function_type){ /** function type is ** _bft_forces : traction function is given ** _bft_stress : stress function is given */ + GhostType ghost_type = _not_ghost; - std::stringstream name; - name << id << ":solidmechanics:imposed_traction"; - Vector traction_funct(0, spatial_dimension,name.str()); - name.clear(); - name << id << ":solidmechanics:imposed_stresses"; - Vector stress_funct(0, spatial_dimension*spatial_dimension,name.str()); - name.clear(); - name << id << ":solidmechanics:quad_coords"; - Vector quad_coords(0,spatial_dimension,"quad_coords"); + std::stringstream name; name << id << ":imposed_traction"; + Vector traction_funct(0, spatial_dimension, name.str()); + + name.clear(); name << id << ":imposed_stresses"; + Vector stress_funct(0, spatial_dimension*spatial_dimension, name.str()); + + name.clear(); name << id << ":quad_coords"; + Vector quad_coords(0, spatial_dimension, name.str()); UInt offset = 0; switch(function_type) { case _bft_stress: offset = spatial_dimension * spatial_dimension; break; case _bft_forces: offset = spatial_dimension; break; } //prepare the loop over element types - const Mesh::ConnectivityTypeList & type_list = getFEMBoundary().getMesh().getConnectivityTypeList(); + const Mesh::ConnectivityTypeList & type_list = getFEMBoundary().getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != getFEMBoundary().getElementDimension()) continue; - UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(*it); - UInt nb_element = getFEMBoundary().getMesh().getNbElement(*it); + UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(*it, ghost_type); + UInt nb_element = getFEMBoundary().getMesh().getNbElement(*it, ghost_type); getFEMBoundary().interpolateOnQuadraturePoints(getFEMBoundary().getMesh().getNodes(), - quad_coords, spatial_dimension, (*it)); + quad_coords, spatial_dimension, *it, ghost_type); Real * imposed_val = NULL; switch(function_type) { case _bft_stress: stress_funct.resize(nb_element*nb_quad); imposed_val = stress_funct.values; break; case _bft_forces: traction_funct.resize(nb_element*nb_quad); imposed_val = traction_funct.values; break; } /// sigma/tractions on each quadrature points Real * qcoord = quad_coords.values; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { myf(qcoord, imposed_val); imposed_val += offset; qcoord += spatial_dimension; } } switch(function_type) { case _bft_stress: - computeForcesByStressTensor(stress_funct,(*it)); break; + computeForcesByStressTensor(stress_funct, *it, ghost_type); break; case _bft_forces: - computeForcesByTractionVector(traction_funct,(*it)); break; + computeForcesByTractionVector(traction_funct, *it, ghost_type); break; } } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeForcesByStressTensor(const Vector & stresses, - const ElementType & type){ + const ElementType & type, + const GhostType & ghost_type){ AKANTU_DEBUG_IN(); - UInt nb_element = getFEMBoundary().getMesh().getNbElement(type); - UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(type); + UInt nb_element = getFEMBoundary().getMesh().getNbElement(type, ghost_type); + UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(type, ghost_type); // check dimension match AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == getFEMBoundary().getElementDimension(), "element type dimension does not match the dimension of boundaries : " << getFEMBoundary().getElementDimension() << " != " << Mesh::getSpatialDimension(type)); // check size of the vector AKANTU_DEBUG_ASSERT(stresses.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(stresses.getNbComponent() == spatial_dimension*spatial_dimension, "the number of components should be the dimension of 2-tensors"); std::stringstream name; - name << id << ":solidmechanics:" << type << ":traction_boundary"; + name << id << ":traction_boundary:" << type; Vector funct(nb_element*nb_quad, spatial_dimension,name.str()); - const Vector & normals_on_quad = getFEMBoundary().getNormalsOnQuadPoints(type); - Math::matrix_vector(spatial_dimension,spatial_dimension,stresses,normals_on_quad,funct); - computeForcesByTractionVector(funct,type); + const Vector & normals_on_quad = getFEMBoundary().getNormalsOnQuadPoints(type, ghost_type); + + Math::matrix_vector(spatial_dimension, spatial_dimension, + stresses,normals_on_quad, funct); + + computeForcesByTractionVector(funct, type, ghost_type); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel:: computeForcesByTractionVector(const Vector & tractions, - const ElementType & type){ + const ElementType & type, + const GhostType & ghost_type){ AKANTU_DEBUG_IN(); - - UInt nb_element = getFEMBoundary().getMesh().getNbElement(type); + + UInt nb_element = getFEMBoundary().getMesh().getNbElement(type, ghost_type); UInt nb_nodes_per_element = getFEMBoundary().getMesh().getNbNodesPerElement(type); - UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(type); + UInt nb_quad = getFEMBoundary().getNbQuadraturePoints(type, ghost_type); // check dimension match - AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) + AKANTU_DEBUG_ASSERT(Mesh::getSpatialDimension(type) == getFEMBoundary().getElementDimension(), "element type dimension does not match " <<"the dimension of boundaries : " << getFEMBoundary().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() == spatial_dimension, "the number of components should be " << "the spatial dimension of the problem"); // do a complete copy of the vector - Vector funct(tractions,true); + Vector funct(tractions, true); + // extend the vector to multiply by the shapes (prepare to assembly) funct.extendComponentsInterlaced(nb_nodes_per_element,spatial_dimension); + // multiply by the shapes Real * funct_val = funct.values; Real * shapes_val = (getFEMBoundary().getShapes(type)).values; for (UInt el = 0; el < nb_element; ++el) { for (UInt q = 0; q < nb_quad; ++q) { for (UInt n = 0; n < nb_nodes_per_element; ++n,++shapes_val) { for (UInt i = 0; i < spatial_dimension; ++i) { *funct_val++ *= *shapes_val; } } } } // allocate the vector that will contain the integrated values std::stringstream name; - name << id << ":solidmechanics:" << type << ":integral_boundary"; + name << id << ":integral_boundary:" << type; Vector int_funct(nb_element, spatial_dimension*nb_nodes_per_element,name.str()); + //do the integration - getFEMBoundary().integrate(funct, int_funct, spatial_dimension*nb_nodes_per_element, type); + getFEMBoundary().integrate(funct, int_funct, spatial_dimension*nb_nodes_per_element, type, ghost_type); + // assemble the result into force vector getFEMBoundary().assembleVector(int_funct, const_cast &>(getForce()), dof_synchronizer->getLocalDOFEquationNumbers(), spatial_dimension, - type); + type, ghost_type); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model_inline_impl.cc b/model/solid_mechanics/solid_mechanics_model_inline_impl.cc index dc23aa6f8..d1f749f6c 100644 --- a/model/solid_mechanics/solid_mechanics_model_inline_impl.cc +++ b/model/solid_mechanics/solid_mechanics_model_inline_impl.cc @@ -1,391 +1,395 @@ /** * @file solid_mechanics_model_inline_impl.cc * @author Nicolas Richart * @date Thu Jul 29 12:07:04 2010 * * @brief Implementation of the inline functions of the SolidMechanicsModel class * * @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 . * */ /* -------------------------------------------------------------------------- */ inline Material & SolidMechanicsModel::getMaterial(UInt mat_index) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The model " << id << " has no material no "<< mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ inline const Material & SolidMechanicsModel::getMaterial(UInt mat_index) const { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(mat_index < materials.size(), "The model " << id << " has no material no "<< mat_index); AKANTU_DEBUG_OUT(); return *materials[mat_index]; } /* -------------------------------------------------------------------------- */ template UInt SolidMechanicsModel::readCustomMaterial(const std::string & filename, const std::string & keyword) { Parser parser; parser.open(filename); std::string key = keyword; to_lower(key); std::string mat_name = parser.getNextSection("material"); while (mat_name != ""){ if (mat_name == key) break; mat_name = parser.getNextSection("material"); } if (mat_name != key) AKANTU_DEBUG_ERROR("material " << key << " not found in file " << filename); std::stringstream sstr_mat; sstr_mat << id << ":" << materials.size() << ":" << key; MaterialID mat_id = sstr_mat.str(); Material * mat = parser.readSection(*this,mat_id); materials.push_back(mat); return materials.size();; } /* -------------------------------------------------------------------------- */ inline FEM & SolidMechanicsModel::getFEMBoundary(std::string name) { return dynamic_cast(getFEMClassBoundary(name)); } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToPack(const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifndef AKANTU_NDEBUG size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check) #endif switch(tag) { case _gst_smm_mass: { size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector break; } case _gst_smm_for_strain: { size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement - UInt mat = element_material[element.type]->values[element.element]; + UInt mat = element_material(element.type, _not_ghost)->values[element.element]; size += materials[mat]->getNbDataToPack(element, tag); break; } case _gst_smm_boundary: { // force, displacement, boundary size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool)); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToUnpack(const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); #ifndef AKANTU_NDEBUG size += spatial_dimension * sizeof(Real); /// position of the barycenter of the element (only for check) #endif switch(tag) { case _gst_smm_mass: { size += nb_nodes_per_element * sizeof(Real) * spatial_dimension; // mass vector break; } case _gst_smm_for_strain: { size += nb_nodes_per_element * spatial_dimension * sizeof(Real); // displacement - UInt mat = ghost_element_material[element.type]->values[element.element]; + UInt mat = element_material(element.type, _ghost)->values[element.element]; size += materials[mat]->getNbDataToPack(element, tag); break; } case _gst_smm_boundary: { // force, displacement, boundary size += nb_nodes_per_element * spatial_dimension * (2 * sizeof(Real) + sizeof(bool)); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); + GhostType ghost_type = _not_ghost; + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; - UInt * conn = mesh.getConnectivity(element.type).values; + UInt * conn = mesh.getConnectivity(element.type, ghost_type).values; #ifndef AKANTU_NDEBUG types::RVector barycenter(spatial_dimension); - mesh.getBarycenter(element.element, element.type, barycenter.storage()); + mesh.getBarycenter(element.element, element.type, barycenter.storage(), ghost_type); buffer << barycenter; #endif switch(tag) { case _gst_smm_mass: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; Vector::iterator it_mass = mass->begin(spatial_dimension); buffer << it_mass[offset_conn]; } break; } case _gst_smm_for_strain: { Vector::iterator it_disp = displacement->begin(spatial_dimension); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer << it_disp[offset_conn]; } - UInt mat = element_material[element.type]->values[element.element]; + UInt mat = element_material(element.type, ghost_type)->values[element.element]; materials[mat]->packData(buffer, element, tag); break; } case _gst_smm_boundary: { Vector::iterator it_force = force->begin(spatial_dimension); Vector::iterator it_velocity = velocity->begin(spatial_dimension); Vector::iterator > it_boundary = boundary->begin(spatial_dimension); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer << it_force [offset_conn]; buffer << it_velocity[offset_conn]; buffer << it_boundary[offset_conn]; } break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); + GhostType ghost_type = _ghost; + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(element.type); UInt el_offset = element.element * nb_nodes_per_element; - UInt * conn = mesh.getConnectivity(element.type,_ghost).values; + UInt * conn = mesh.getConnectivity(element.type, ghost_type).values; #ifndef AKANTU_NDEBUG types::RVector barycenter_loc(spatial_dimension); - mesh.getBarycenter(element.element, element.type, barycenter_loc.storage(), _ghost); + mesh.getBarycenter(element.element, element.type, barycenter_loc.storage(), ghost_type); types::RVector barycenter(spatial_dimension); buffer >> barycenter; Real tolerance = 1e-15; for (UInt i = 0; i < spatial_dimension; ++i) { if(!(std::abs(barycenter(i) - barycenter_loc(i)) <= tolerance)) AKANTU_DEBUG_ERROR("Unpacking an unknown value for the element : " << element << "(barycenter[" << i << "] = " << barycenter_loc(i) << " and buffer[" << i << "] = " << barycenter(i) << ")"); } #endif switch(tag) { case _gst_smm_mass: { for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; Vector::iterator it_mass = mass->begin(spatial_dimension); buffer >> it_mass[offset_conn]; } break; } case _gst_smm_for_strain: { Vector::iterator it_disp = displacement->begin(spatial_dimension); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer >> it_disp[offset_conn]; } - UInt mat = ghost_element_material[element.type]->values[element.element]; + UInt mat = element_material(element.type, ghost_type)->values[element.element]; materials[mat]->unpackData(buffer, element, tag); break; } case _gst_smm_boundary: { Vector::iterator it_force = force->begin(spatial_dimension); Vector::iterator it_velocity = velocity->begin(spatial_dimension); Vector::iterator > it_boundary = boundary->begin(spatial_dimension); for (UInt n = 0; n < nb_nodes_per_element; ++n) { UInt offset_conn = conn[el_offset + n]; buffer >> it_force [offset_conn]; buffer >> it_velocity[offset_conn]; buffer >> it_boundary[offset_conn]; } break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToPack(SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes = mesh.getNbNodes(); switch(tag) { case _gst_smm_uv: { size += nb_nodes * sizeof(Real) * spatial_dimension * 2; break; } case _gst_smm_mass: { size += nb_nodes * sizeof(Real) * spatial_dimension; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline UInt SolidMechanicsModel::getNbDataToUnpack(SynchronizationTag tag) const { AKANTU_DEBUG_IN(); UInt size = 0; UInt nb_nodes = mesh.getNbNodes(); switch(tag) { case _gst_smm_uv: { size += nb_nodes * sizeof(Real) * spatial_dimension * 2; break; } case _gst_smm_mass: { size += nb_nodes * sizeof(Real) * spatial_dimension; break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); return size; } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); switch(tag) { case _gst_smm_uv: { for (UInt d = 0; d < spatial_dimension; ++d) { buffer << (*displacement)(index,d); buffer << (*velocity)(index,d); } break; } case _gst_smm_mass: { AKANTU_DEBUG_INFO("pack mass of node " << index << " which is " << (*mass)(index,0)); buffer << (*mass)(index,0); buffer << (*mass)(index,1); buffer << (*mass)(index,2); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ inline void SolidMechanicsModel::unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const { AKANTU_DEBUG_IN(); switch(tag) { case _gst_smm_uv: { for (UInt d = 0; d < spatial_dimension; ++d) { buffer >> (*displacement)(index,d); buffer >> (*velocity)(index,d); } break; } case _gst_smm_mass: { AKANTU_DEBUG_INFO("mass of node " << index << " was " << (*mass)(index,0)); buffer >> (*mass)(index,0); buffer >> (*mass)(index,1); buffer >> (*mass)(index,2); AKANTU_DEBUG_INFO("mass of node " << index << " is now " << (*mass)(index,0)); break; } default: { AKANTU_DEBUG_ERROR("Unknown ghost synchronization tag : " << tag); } } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ diff --git a/model/solid_mechanics/solid_mechanics_model_mass.cc b/model/solid_mechanics/solid_mechanics_model_mass.cc index 0c85e96fc..d3b92c644 100644 --- a/model/solid_mechanics/solid_mechanics_model_mass.cc +++ b/model/solid_mechanics/solid_mechanics_model_mass.cc @@ -1,162 +1,157 @@ /** * @file solid_mechanics_model_mass.cc * @author Nicolas Richart * @date Mon Oct 4 15:21:23 2010 * * @brief function handling mass computation * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped() { AKANTU_DEBUG_IN(); UInt nb_nodes = mesh.getNbNodes(); mass->clear(); assembleMassLumped(_not_ghost); assembleMassLumped(_ghost); /// for not connected nodes put mass to one in order to avoid /// wrong range in paraview Real * mass_values = mass->values; for (UInt i = 0; i < nb_nodes; ++i) { if (fabs(mass_values[i]) < std::numeric_limits::epsilon() || Math::isnan(mass_values[i])) mass_values[i] = 1.; } synch_registry->synchronize(_gst_smm_mass); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMassLumped(GhostType ghost_type) { AKANTU_DEBUG_IN(); FEM & fem = getFEM(); Vector rho_1(0,1); const Mesh::ConnectivityTypeList & type_list = fem.getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; ElementType type = *it; computeRho(rho_1, type, ghost_type); AKANTU_DEBUG_ASSERT(dof_synchronizer, "DOFSynchronizer number must not be initialized"); fem.assembleFieldLumped(rho_1, spatial_dimension,*mass, dof_synchronizer->getLocalDOFEquationNumbers(), type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass() { AKANTU_DEBUG_IN(); if(!dof_synchronizer) dof_synchronizer = new DOFSynchronizer(mesh, spatial_dimension); UInt nb_global_node = mesh.getNbGlobalNodes(); std::stringstream sstr; sstr << id << ":mass_matrix"; mass_matrix = new SparseMatrix(nb_global_node * spatial_dimension, _symmetric, spatial_dimension, sstr.str(), memory_id); mass_matrix->buildProfile(mesh, *dof_synchronizer); assembleMass(_not_ghost); // assembleMass(_ghost); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::assembleMass(GhostType ghost_type) { AKANTU_DEBUG_IN(); MyFEMType & fem = getFEMClass(); Vector rho_1(0,1); //UInt nb_element; mass_matrix->clear(); const Mesh::ConnectivityTypeList & type_list = fem.getMesh().getConnectivityTypeList(ghost_type); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; ElementType type = *it; computeRho(rho_1, type, ghost_type); fem.assembleFieldMatrix(rho_1, spatial_dimension, *mass_matrix, type, ghost_type); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::computeRho(Vector & rho, ElementType type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Material ** mat_val = &(materials.at(0)); - UInt * elem_mat_val; FEM & fem = getFEM(); UInt nb_element = fem.getMesh().getNbElement(type,ghost_type); - if(ghost_type == _not_ghost) { - elem_mat_val = element_material[type]->values; - } else { - elem_mat_val = ghost_element_material[type]->values; - } + UInt * elem_mat_val = element_material(type, ghost_type)->values; - UInt nb_quadrature_points = fem.getNbQuadraturePoints(type); + UInt nb_quadrature_points = fem.getNbQuadraturePoints(type, ghost_type); rho.resize(nb_element * nb_quadrature_points); Real * rho_1_val = rho.values; /// compute @f$ rho @f$ for each nodes of each element for (UInt el = 0; el < nb_element; ++el) { Real mat_rho = mat_val[elem_mat_val[el]]->getRho(); /// here rho is constant in an element for (UInt n = 0; n < nb_quadrature_points; ++n) { *rho_1_val++ = mat_rho; } } AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/model/solid_mechanics/solid_mechanics_model_material.cc b/model/solid_mechanics/solid_mechanics_model_material.cc index a64985439..a81e4f50c 100644 --- a/model/solid_mechanics/solid_mechanics_model_material.cc +++ b/model/solid_mechanics/solid_mechanics_model_material.cc @@ -1,103 +1,93 @@ /** * @file solid_mechanics_model_material.cc * @author Guillaume ANCIAUX * @date Thu Nov 25 10:48:53 2010 * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "solid_mechanics_model.hh" #include "material.hh" #include "aka_math.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::readMaterials(const std::string & filename) { Parser parser; parser.open(filename); std::string mat_type = parser.getNextSection("material"); UInt mat_count = 0; while (mat_type != ""){ std::stringstream sstr_mat; sstr_mat << id << ":" << mat_count++ << ":" << mat_type; Material * material; MaterialID mat_id = sstr_mat.str(); /// read the material properties if(mat_type == "elastic") material = parser.readSection (*this, mat_id); else if(mat_type == "elastic_caughey") material = parser.readSection(*this, mat_id); else if(mat_type == "damage") material = parser.readSection (*this, mat_id); else if(mat_type == "mazars") material = parser.readSection (*this, mat_id); else if(mat_type == "neohookean") material = parser.readSection (*this, mat_id); else AKANTU_DEBUG_ERROR("Malformed material file : unknown material type " << mat_type); materials.push_back(material); mat_type = parser.getNextSection("material"); } } /* -------------------------------------------------------------------------- */ void SolidMechanicsModel::initMaterials() { AKANTU_DEBUG_ASSERT(materials.size() != 0, "No material to initialize !"); Material ** mat_val = &(materials.at(0)); - /// fill the element filters of the materials using the element_material arrays - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(_not_ghost); - Mesh::ConnectivityTypeList::const_iterator it; - for(it = type_list.begin(); it != type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - - UInt nb_element = mesh.getNbElement(*it); - UInt * elem_mat_val = element_material[*it]->values; - - for (UInt el = 0; el < nb_element; ++el) { - mat_val[elem_mat_val[el]]->addElement(*it, el); - } - } - /// @todo synchronize element material - /// fill the element filters of the materials using the element_material arrays - const Mesh::ConnectivityTypeList & ghost_type_list = - mesh.getConnectivityTypeList(_ghost); - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + + /// fill the element filters of the materials using the element_material arrays + const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(gt); + Mesh::ConnectivityTypeList::const_iterator it; + for(it = type_list.begin(); it != type_list.end(); ++it) { + if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - UInt nb_element = mesh.getNbElement(*it,_ghost); - UInt * elem_mat_val = ghost_element_material[*it]->values; + UInt nb_element = mesh.getNbElement(*it, gt); + UInt * elem_mat_val = element_material(*it, gt)->values; - for (UInt el = 0; el < nb_element; ++el) { - mat_val[elem_mat_val[el]]->addGhostElement(*it, el); + for (UInt el = 0; el < nb_element; ++el) { + mat_val[elem_mat_val[el]]->addElement(*it, el, gt); + } } } std::vector::iterator mat_it; for(mat_it = materials.begin(); mat_it != materials.end(); ++mat_it) { /// init internals properties (*mat_it)->initMaterial(); } } __END_AKANTU__ diff --git a/solver/sparse_matrix.cc b/solver/sparse_matrix.cc index b563b4568..8f502feec 100644 --- a/solver/sparse_matrix.cc +++ b/solver/sparse_matrix.cc @@ -1,419 +1,419 @@ /** * @file sparse_matrix.cc * @author Nicolas Richart * @date Tue Oct 26 18:25:07 2010 * * @brief implementation of the SparseMatrix class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "sparse_matrix.hh" #include "static_communicator.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(UInt size, const SparseMatrixType & sparse_matrix_type, UInt nb_degre_of_freedom, const SparseMatrixID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), sparse_matrix_type(sparse_matrix_type), nb_degre_of_freedom(nb_degre_of_freedom), size(size), nb_non_zero(0), irn(0,1,"irn"), jcn(0,1,"jcn"), a(0,1,"A") { AKANTU_DEBUG_IN(); StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); nb_proc = comm->getNbProc(); dof_synchronizer = NULL; irn_save = NULL; jcn_save = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::SparseMatrix(const SparseMatrix & matrix, const SparseMatrixID & id, const MemoryID & memory_id) : Memory(memory_id), id(id), sparse_matrix_type(matrix.sparse_matrix_type), nb_degre_of_freedom(matrix.nb_degre_of_freedom), size(matrix.size), nb_proc(matrix.nb_proc), nb_non_zero(matrix.nb_non_zero), irn(matrix.irn, true), jcn(matrix.jcn, true), a(matrix.getA(), true), irn_jcn_k(matrix.irn_jcn_k) { AKANTU_DEBUG_IN(); size_save = 0; irn_save = NULL; jcn_save = NULL; dof_synchronizer = matrix.dof_synchronizer; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ SparseMatrix::~SparseMatrix() { AKANTU_DEBUG_IN(); // if (irn_jcn_to_k) delete irn_jcn_to_k; if(irn_save) delete irn_save; if(jcn_save) delete jcn_save; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::buildProfile(const Mesh & mesh, const DOFSynchronizer & dof_synchronizer) { AKANTU_DEBUG_IN(); // if(irn_jcn_to_k) delete irn_jcn_to_k; // irn_jcn_to_k = new std::map, UInt>; clearProfile(); this->dof_synchronizer = &const_cast(dof_synchronizer); coordinate_list_map::iterator irn_jcn_k_it; Int * eq_nb_val = dof_synchronizer.getGlobalDOFEquationNumbers().values; const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if (Mesh::getSpatialDimension(*it) != mesh.getSpatialDimension()) continue; UInt nb_element = mesh.getNbElement(*it); UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(*it); UInt size_mat = nb_nodes_per_element * nb_degre_of_freedom; - UInt * conn_val = mesh.getConnectivity(*it).values; + UInt * conn_val = mesh.getConnectivity(*it, _not_ghost).values; Int * local_eq_nb_val = new Int[nb_degre_of_freedom * nb_nodes_per_element]; for (UInt e = 0; e < nb_element; ++e) { Int * tmp_local_eq_nb_val = local_eq_nb_val; for (UInt i = 0; i < nb_nodes_per_element; ++i) { UInt n = conn_val[i]; for (UInt d = 0; d < nb_degre_of_freedom; ++d) { *tmp_local_eq_nb_val++ = eq_nb_val[n * nb_degre_of_freedom + d]; } // memcpy(tmp_local_eq_nb_val, eq_nb_val + n * nb_degre_of_freedom, nb_degre_of_freedom * sizeof(Int)); // tmp_local_eq_nb_val += nb_degre_of_freedom; } for (UInt i = 0; i < size_mat; ++i) { UInt c_irn = local_eq_nb_val[i]; if(c_irn < size) { UInt j_start = (sparse_matrix_type == _symmetric) ? i : 0; for (UInt j = j_start; j < size_mat; ++j) { UInt c_jcn = local_eq_nb_val[j]; if(c_jcn < size) { KeyCOO irn_jcn = key(c_irn, c_jcn); irn_jcn_k_it = irn_jcn_k.find(irn_jcn); if (irn_jcn_k_it == irn_jcn_k.end()) { irn_jcn_k[irn_jcn] = nb_non_zero; irn.push_back(c_irn + 1); jcn.push_back(c_jcn + 1); nb_non_zero++; } } } } } conn_val += nb_nodes_per_element; } delete [] local_eq_nb_val; } a.resize(nb_non_zero); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::applyBoundary(const Vector & boundary) { AKANTU_DEBUG_IN(); const DOFSynchronizer::GlobalEquationNumberMap & local_eq_num_to_global = dof_synchronizer->getGlobalEquationNumberToLocal(); Int * irn_val = irn.values; Int * jcn_val = jcn.values; Real * a_val = a.values; for (UInt i = 0; i < nb_non_zero; ++i) { UInt ni = local_eq_num_to_global.find(*irn_val - 1)->second; UInt nj = local_eq_num_to_global.find(*jcn_val - 1)->second; if(boundary.values[ni] || boundary.values[nj]) { if (*irn_val != *jcn_val) *a_val = 0; else { if(dof_synchronizer->getDOFTypes()(ni) >= 0) *a_val = 0; else *a_val = 1; } } irn_val++; jcn_val++; a_val++; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::removeBoundary(const Vector & boundary) { AKANTU_DEBUG_IN(); if(irn_save) delete irn_save; if(jcn_save) delete jcn_save; irn_save = new Vector(irn, true); jcn_save = new Vector(jcn, true); UInt n = boundary.getSize()*boundary.getNbComponent(); UInt * perm = new UInt[n]; size_save = size; size = 0; for (UInt i = 0; i < n; ++i) { if(!boundary.values[i]) { perm[i] = size; // std::cout << "perm["<< i <<"] = " << size << std::endl; size++; } } for (UInt i = 0; i < nb_non_zero;) { if(boundary.values[irn.at(i) - 1] || boundary.values[jcn.at(i) - 1]) { irn.erase(i); jcn.erase(i); a.erase(i); nb_non_zero--; } else { irn.values[i] = perm[irn.values[i] - 1] + 1; jcn.values[i] = perm[jcn.values[i] - 1] + 1; i++; } } delete [] perm; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::restoreProfile() { AKANTU_DEBUG_IN(); irn.resize(irn_save->getSize()); jcn.resize(jcn_save->getSize()); nb_non_zero = irn.getSize(); a.resize(nb_non_zero); size = size_save; memcpy(irn.values, irn_save->values, irn.getSize()*sizeof(Int)); memcpy(jcn.values, jcn_save->values, jcn.getSize()*sizeof(Int)); delete irn_save; irn_save = NULL; delete jcn_save; jcn_save = NULL; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::saveProfile(const std::string & filename) { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate pattern"; if(sparse_matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; UInt m = size; outfile << m << " " << m << " " << nb_non_zero << std::endl; for (UInt i = 0; i < nb_non_zero; ++i) { outfile << irn.values[i] << " " << jcn.values[i] << " 1" << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::saveMatrix(const std::string & filename) { AKANTU_DEBUG_IN(); std::ofstream outfile; outfile.precision(std::numeric_limits::digits10); outfile.open(filename.c_str()); outfile << "%%MatrixMarket matrix coordinate real"; if(sparse_matrix_type == _symmetric) outfile << " symmetric"; else outfile << " general"; outfile << std::endl; outfile << size << " " << size << " " << nb_non_zero << std::endl; for (UInt i = 0; i < nb_non_zero; ++i) { outfile << irn(i) << " " << jcn(i) << " " << a(i) << std::endl; } outfile.close(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ Vector & operator*=(Vector & vect, const SparseMatrix & mat) { AKANTU_DEBUG_IN(); // AKANTU_DEBUG_ASSERT((vect.getSize()*vect.getNbComponent() == mat.getSize()) && // (vect.getNbComponent() == mat.getNbDegreOfFreedom()), // "The size of the matrix and the vector do not match"); const SparseMatrixType & sparse_matrix_type = mat.getSparseMatrixType(); DOFSynchronizer * dof_synchronizer = mat.getDOFSynchronizerPointer(); UInt nb_non_zero = mat.getNbNonZero(); Real * tmp = new Real [vect.getNbComponent() * vect.getSize()]; std::fill_n(tmp, vect.getNbComponent() * vect.getSize(), 0); Int * i_val = mat.getIRN().values; Int * j_val = mat.getJCN().values; Real * a_val = mat.getA().values; Real * vect_val = vect.values; for (UInt k = 0; k < nb_non_zero; ++k) { UInt i = *(i_val++); UInt j = *(j_val++); Real a = *(a_val++); UInt local_i = i - 1; UInt local_j = j - 1; if(dof_synchronizer) { local_i = dof_synchronizer->getDOFLocalID(local_i); local_j = dof_synchronizer->getDOFLocalID(local_j); } tmp[local_i] += a * vect_val[local_j]; if(sparse_matrix_type == _symmetric && (local_i != local_j)) tmp[local_j] += a * vect_val[local_i]; } memcpy(vect_val, tmp, vect.getNbComponent() * vect.getSize() * sizeof(Real)); delete [] tmp; if(dof_synchronizer) dof_synchronizer->reduceSynchronize >(vect); AKANTU_DEBUG_OUT(); return vect; } /* -------------------------------------------------------------------------- */ void SparseMatrix::copyContent(const SparseMatrix & matrix) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(), "The to matrix don't have the same profiles"); memcpy(a.values, matrix.getA().values, nb_non_zero * sizeof(Real)); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void SparseMatrix::add(const SparseMatrix & matrix, Real alpha) { AKANTU_DEBUG_ASSERT(nb_non_zero == matrix.getNbNonZero(), "The to matrix don't have the same profiles"); Real * a_val = a.values; Real * b_val = matrix.a.values; for (UInt n = 0; n < nb_non_zero; ++n) { *a_val++ += alpha * *b_val++; } } /* -------------------------------------------------------------------------- */ void SparseMatrix::lump(Vector & lumped) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT((lumped.getNbComponent() == nb_degre_of_freedom), "The size of the matrix and the vector do not match"); UInt vect_size = size / nb_degre_of_freedom; if(dof_synchronizer) vect_size = dof_synchronizer->getNbDOFs() / nb_degre_of_freedom; lumped.resize(vect_size); lumped.clear(); Int * i_val = irn.values; Int * j_val = jcn.values; Real * a_val = a.values; Real * vect_val = lumped.values; for (UInt k = 0; k < nb_non_zero; ++k) { UInt i = *(i_val++); UInt j = *(j_val++); Real a = *(a_val++); UInt local_i = i - 1; UInt local_j = j - 1; if(dof_synchronizer) { local_i = dof_synchronizer->getDOFLocalID(local_i); local_j = dof_synchronizer->getDOFLocalID(local_j); } vect_val[local_i] += a; if(sparse_matrix_type == _symmetric && (i != j)) vect_val[local_j] += a; } if(dof_synchronizer) dof_synchronizer->reduceSynchronize >(lumped); AKANTU_DEBUG_OUT(); } __END_AKANTU__ diff --git a/synchronizer/distributed_synchronizer.cc b/synchronizer/distributed_synchronizer.cc index 02948ebed..31e938c78 100644 --- a/synchronizer/distributed_synchronizer.cc +++ b/synchronizer/distributed_synchronizer.cc @@ -1,881 +1,862 @@ /** * @file distributed_synchronizer.cc * @author Nicolas Richart * @date Thu Aug 26 16:36:21 2010 * * @brief implementation of a communicator using a static_communicator for real * send/receive * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "distributed_synchronizer.hh" #include "static_communicator.hh" #include "mesh_utils.hh" /* -------------------------------------------------------------------------- */ __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ DistributedSynchronizer::DistributedSynchronizer(SynchronizerID id, MemoryID memory_id) : Synchronizer(id, memory_id), static_communicator(StaticCommunicator::getStaticCommunicator()) { AKANTU_DEBUG_IN(); - for (UInt t = _not_defined; t < _max_element_type; ++t) { - element_to_send_offset [t] = NULL; - element_to_send [t] = NULL; - element_to_receive_offset[t] = NULL; - element_to_receive [t] = NULL; - } - nb_proc = static_communicator->getNbProc(); rank = static_communicator->whoAmI(); send_buffer = new CommunicationBuffer[nb_proc]; recv_buffer = new CommunicationBuffer[nb_proc]; send_element = new std::vector[nb_proc]; recv_element = new std::vector[nb_proc]; size_to_send.clear(); size_to_receive.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ DistributedSynchronizer::~DistributedSynchronizer() { AKANTU_DEBUG_IN(); for (UInt p = 0; p < nb_proc; ++p) { send_buffer[p].resize(0); recv_buffer[p].resize(0); send_element[p].clear(); recv_element[p].clear(); } delete [] send_buffer; delete [] recv_buffer; delete [] send_element; delete [] recv_element; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ DistributedSynchronizer * DistributedSynchronizer:: createDistributedSynchronizerMesh(Mesh & mesh, const MeshPartition * partition, UInt root, SynchronizerID id, MemoryID memory_id) { AKANTU_DEBUG_IN(); const UInt TAG_SIZES = 0; const UInt TAG_CONNECTIVITY = 1; const UInt TAG_DATA = 2; const UInt TAG_PARTITIONS = 3; const UInt TAG_NB_NODES = 4; const UInt TAG_NODES = 5; const UInt TAG_COORDINATES = 6; const UInt TAG_NODES_TYPE = 7; StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); UInt nb_proc = comm->getNbProc(); UInt my_rank = comm->whoAmI(); DistributedSynchronizer * communicator = new DistributedSynchronizer(id, memory_id); if(nb_proc == 1) return communicator; UInt * local_connectivity = NULL; UInt * local_partitions = NULL; UInt * local_data = NULL; Vector * old_nodes = mesh.getNodesGlobalIdsPointer(); Vector * nodes = mesh.getNodesPointer(); UInt spatial_dimension = nodes->getNbComponent(); /* ------------------------------------------------------------------------ */ /* Local (rank == root) */ /* ------------------------------------------------------------------------ */ if(my_rank == root) { AKANTU_DEBUG_ASSERT(partition->getNbPartition() == nb_proc, "The number of partition does not match the number of processors"); /** * connectivity and communications scheme construction */ const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { ElementType type = *it; if(Mesh::getSpatialDimension(type) != mesh.getSpatialDimension()) continue; UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); UInt nb_element = mesh.getNbElement(*it); UInt nb_local_element[nb_proc]; UInt nb_ghost_element[nb_proc]; UInt nb_element_to_send[nb_proc]; memset(nb_local_element, 0, nb_proc*sizeof(UInt)); memset(nb_ghost_element, 0, nb_proc*sizeof(UInt)); memset(nb_element_to_send, 0, nb_proc*sizeof(UInt)); - UInt * partition_num = partition->getPartition(type).values; + UInt * partition_num = partition->getPartition(type, _not_ghost).values; - UInt * ghost_partition = partition->getGhostPartition(type).values; - UInt * ghost_partition_offset = partition->getGhostPartitionOffset(type).values; + UInt * ghost_partition = partition->getGhostPartition(type, _ghost).values; + UInt * ghost_partition_offset = partition->getGhostPartitionOffset(type, _ghost).values; - Mesh::UIntDataMap & uint_data_map = mesh.getUIntDataMap(type); + UIntDataMap & uint_data_map = mesh.getUIntDataMap(type, _not_ghost); UInt nb_tags = uint_data_map.size(); /* -------------------------------------------------------------------- */ /// constructing the reordering structures for (UInt el = 0; el < nb_element; ++el) { nb_local_element[partition_num[el]]++; for (UInt part = ghost_partition_offset[el]; part < ghost_partition_offset[el + 1]; ++part) { nb_ghost_element[ghost_partition[part]]++; } nb_element_to_send[partition_num[el]] += ghost_partition_offset[el + 1] - ghost_partition_offset[el] + 1; } /// allocating buffers UInt * buffers[nb_proc]; UInt * buffers_tmp[nb_proc]; for (UInt p = 0; p < nb_proc; ++p) { UInt size = nb_nodes_per_element * (nb_local_element[p] + nb_ghost_element[p]); buffers[p] = new UInt[size]; buffers_tmp[p] = buffers[p]; } /// copying the local connectivity - UInt * conn_val = mesh.getConnectivity(type).values; + UInt * conn_val = mesh.getConnectivity(type, _not_ghost).values; for (UInt el = 0; el < nb_element; ++el) { memcpy(buffers_tmp[partition_num[el]], conn_val + el * nb_nodes_per_element, nb_nodes_per_element * sizeof(UInt)); buffers_tmp[partition_num[el]] += nb_nodes_per_element; } /// copying the connectivity of ghost element for (UInt el = 0; el < nb_element; ++el) { for (UInt part = ghost_partition_offset[el]; part < ghost_partition_offset[el + 1]; ++part) { UInt proc = ghost_partition[part]; memcpy(buffers_tmp[proc], conn_val + el * nb_nodes_per_element, nb_nodes_per_element * sizeof(UInt)); buffers_tmp[proc] += nb_nodes_per_element; } } UInt names_size = 0; - Mesh::UIntDataMap::iterator it_data; + UIntDataMap::iterator it_data; for(it_data = uint_data_map.begin(); it_data != uint_data_map.end(); ++it_data) { names_size += it_data->first.size() + 1; } /* -------->>>>-SIZE + CONNECTIVITY------------------------------------ */ /// send all connectivity and ghost information to all processors std::vector requests; for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { UInt size[6]; size[0] = (UInt) type; size[1] = nb_local_element[p]; size[2] = nb_ghost_element[p]; size[3] = nb_element_to_send[p]; size[4] = nb_tags; size[5] = names_size; comm->send(size, 6, p, TAG_SIZES); AKANTU_DEBUG_INFO("Sending connectivities to proc " << p); requests.push_back(comm->asyncSend(buffers[p], nb_nodes_per_element * (nb_local_element[p] + nb_ghost_element[p]), p, TAG_CONNECTIVITY)); } else { local_connectivity = buffers[p]; } } /// create the renumbered connectivity AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, local_connectivity, nb_local_element[root], nb_ghost_element[root], type, *old_nodes); comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) { delete [] buffers[p]; } /* -------------------------------------------------------------------- */ for (UInt p = 0; p < nb_proc; ++p) { buffers[p] = new UInt[nb_ghost_element[p] + nb_element_to_send[p]]; buffers_tmp[p] = buffers[p]; } /// splitting the partition information to send them to processors UInt count_by_proc[nb_proc]; memset(count_by_proc, 0, nb_proc*sizeof(UInt)); for (UInt el = 0; el < nb_element; ++el) { *(buffers_tmp[partition_num[el]]++) = ghost_partition_offset[el + 1] - ghost_partition_offset[el]; for (UInt part = ghost_partition_offset[el], i = 0; part < ghost_partition_offset[el + 1]; ++part, ++i) { *(buffers_tmp[partition_num[el]]++) = ghost_partition[part]; } } for (UInt el = 0; el < nb_element; ++el) { for (UInt part = ghost_partition_offset[el], i = 0; part < ghost_partition_offset[el + 1]; ++part, ++i) { *(buffers_tmp[ghost_partition[part]]++) = partition_num[el]; } } /* -------->>>>-PARTITIONS--------------------------------------------- */ /// last data to compute the communication scheme for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { AKANTU_DEBUG_INFO("Sending partition informations to proc " << p); requests.push_back(comm->asyncSend(buffers[p], nb_element_to_send[p] + nb_ghost_element[p], p, TAG_PARTITIONS)); } else { local_partitions = buffers[p]; } } AKANTU_DEBUG_INFO("Creating communications scheme"); communicator->fillCommunicationScheme(local_partitions, nb_local_element[root], nb_ghost_element[root], type); comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) { delete [] buffers[p]; } /* -------------------------------------------------------------------- */ /// send int data assossiated to the mesh if(nb_tags) { UInt uint_names_size = names_size / sizeof(UInt) + (names_size % sizeof(UInt) ? 1 : 0); for (UInt p = 0; p < nb_proc; ++p) { UInt size = nb_tags * (nb_local_element[p] + nb_ghost_element[p]) + uint_names_size; buffers[p] = new UInt[size]; std::fill_n(buffers[p], size, 0); buffers_tmp[p] = buffers[p]; } char * names = new char[names_size]; char * names_tmp = names; memset(names, 0, names_size); for(it_data = uint_data_map.begin(); it_data != uint_data_map.end(); ++it_data) { UInt * data = it_data->second->values; memcpy(names_tmp, it_data->first.data(), it_data->first.size()); names_tmp += it_data->first.size() + 1; /// copying data for the local element for (UInt el = 0; el < nb_element; ++el) { UInt proc = partition_num[el]; *(buffers_tmp[proc]) = data[el]; buffers_tmp[proc]++; } /// copying the data for the ghost element for (UInt el = 0; el < nb_element; ++el) { for (UInt part = ghost_partition_offset[el]; part < ghost_partition_offset[el + 1]; ++part) { UInt proc = ghost_partition[part]; *(buffers_tmp[proc]) = data[el]; buffers_tmp[proc]++; } } } /* -------->>>>-TAGS------------------------------------------------- */ for (UInt p = 0; p < nb_proc; ++p) { memcpy((char *)buffers_tmp[p], names, names_size); if(p != root) { UInt size = nb_tags * (nb_local_element[p] + nb_ghost_element[p]) + uint_names_size; AKANTU_DEBUG_INFO("Sending associated data to proc " << p); requests.push_back(comm->asyncSend(buffers[p], size, p, TAG_DATA)); } else { local_data = buffers[p]; } } MeshUtils::setUIntData(mesh, local_data, nb_tags, type); comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) delete [] buffers[p]; delete [] names; } } /* -------->>>>-SIZE----------------------------------------------------- */ for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { UInt size[6]; size[0] = (UInt) _not_defined; size[1] = 0; size[2] = 0; size[3] = 0; size[4] = 0; size[5] = 0; comm->send(size, 6, p, TAG_SIZES); } } /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ /** * Nodes coordinate construction and synchronization */ std::multimap< UInt, std::pair > nodes_to_proc; /// get the list of nodes to send and send them Real * local_nodes = NULL; UInt nb_nodes_per_proc[nb_proc]; UInt * nodes_per_proc[nb_proc]; /* --------<<<<-NB_NODES + NODES----------------------------------------- */ for (UInt p = 0; p < nb_proc; ++p) { UInt nb_nodes; // UInt * buffer; if(p != root) { AKANTU_DEBUG_INFO("Receiving list of nodes from proc " << p); comm->receive(&nb_nodes, 1, p, TAG_NB_NODES); nodes_per_proc[p] = new UInt[nb_nodes]; nb_nodes_per_proc[p] = nb_nodes; comm->receive(nodes_per_proc[p], nb_nodes, p, TAG_NODES); } else { nb_nodes = old_nodes->getSize(); nb_nodes_per_proc[p] = nb_nodes; nodes_per_proc[p] = old_nodes->values; } /// get the coordinates for the selected nodes Real * nodes_to_send = new Real[nb_nodes * spatial_dimension]; Real * nodes_to_send_tmp = nodes_to_send; for (UInt n = 0; n < nb_nodes; ++n) { memcpy(nodes_to_send_tmp, nodes->values + spatial_dimension * nodes_per_proc[p][n], spatial_dimension * sizeof(Real)); // nodes_to_proc.insert(std::make_pair(buffer[n], std::make_pair(p, n))); nodes_to_send_tmp += spatial_dimension; } /* -------->>>>-COORDINATES-------------------------------------------- */ if(p != root) { /// send them for distant processors AKANTU_DEBUG_INFO("Sending coordinates to proc " << p); comm->send(nodes_to_send, nb_nodes * spatial_dimension, p, TAG_COORDINATES); delete [] nodes_to_send; } else { /// save them for local processor local_nodes = nodes_to_send; } } /// construct the local nodes coordinates UInt nb_nodes = old_nodes->getSize(); nodes->resize(nb_nodes); memcpy(nodes->values, local_nodes, nb_nodes * spatial_dimension * sizeof(Real)); delete [] local_nodes; Vector * nodes_type_per_proc[nb_proc]; for (UInt p = 0; p < nb_proc; ++p) { nodes_type_per_proc[p] = new Vector(nb_nodes_per_proc[p]); } communicator->fillNodesType(mesh); /* --------<<<<-NODES_TYPE-1--------------------------------------------- */ for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { AKANTU_DEBUG_INFO("Receiving first nodes types from proc " << p); comm->receive(nodes_type_per_proc[p]->values, nb_nodes_per_proc[p], p, TAG_NODES_TYPE); } else { nodes_type_per_proc[p]->copy(mesh.getNodesType()); } for (UInt n = 0; n < nb_nodes_per_proc[p]; ++n) { if((*nodes_type_per_proc[p])(n) == -2) nodes_to_proc.insert(std::make_pair(nodes_per_proc[p][n], std::make_pair(p, n))); } } std::multimap< UInt, std::pair >::iterator it_node; std::pair< std::multimap< UInt, std::pair >::iterator, std::multimap< UInt, std::pair >::iterator > it_range; for (UInt i = 0; i < mesh.nb_global_nodes; ++i) { it_range = nodes_to_proc.equal_range(i); if(it_range.first == nodes_to_proc.end() || it_range.first->first != i) continue; UInt node_type = (it_range.first)->second.first; for (it_node = it_range.first; it_node != it_range.second; ++it_node) { UInt proc = it_node->second.first; UInt node = it_node->second.second; if(proc != node_type) nodes_type_per_proc[proc]->values[node] = node_type; } } /* -------->>>>-NODES_TYPE-2--------------------------------------------- */ std::vector requests; for (UInt p = 0; p < nb_proc; ++p) { if(p != root) { AKANTU_DEBUG_INFO("Sending nodes types to proc " << p); requests.push_back(comm->asyncSend(nodes_type_per_proc[p]->values, nb_nodes_per_proc[p], p, TAG_NODES_TYPE)); } else { mesh.getNodesTypePointer()->copy(*nodes_type_per_proc[p]); } } comm->waitAll(requests); comm->freeCommunicationRequest(requests); requests.clear(); for (UInt p = 0; p < nb_proc; ++p) { if(p != root) delete [] nodes_per_proc[p]; delete nodes_type_per_proc[p]; } /* ---------------------------------------------------------------------- */ /* Distant (rank != root) */ /* ---------------------------------------------------------------------- */ } else { /** * connectivity and communications scheme construction on distant processors */ ElementType type = _not_defined; do { /* --------<<<<-SIZE--------------------------------------------------- */ UInt size[6]; comm->receive(size, 6, root, TAG_SIZES); type = (ElementType) size[0]; UInt nb_local_element = size[1]; UInt nb_ghost_element = size[2]; UInt nb_element_to_send = size[3]; UInt nb_tags = size[4]; UInt names_size = size[5]; UInt uint_names_size = names_size / sizeof(UInt) + (names_size % sizeof(UInt) ? 1 : 0); if(type != _not_defined) { UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); /* --------<<<<-CONNECTIVITY----------------------------------------- */ local_connectivity = new UInt[(nb_local_element + nb_ghost_element) * nb_nodes_per_element]; AKANTU_DEBUG_INFO("Receiving connectivities from proc " << root); comm->receive(local_connectivity, nb_nodes_per_element * (nb_local_element + nb_ghost_element), root, TAG_CONNECTIVITY); AKANTU_DEBUG_INFO("Renumbering local connectivities"); MeshUtils::renumberMeshNodes(mesh, local_connectivity, nb_local_element, nb_ghost_element, type, *old_nodes); delete [] local_connectivity; /* --------<<<<-PARTITIONS--------------------------------------------- */ local_partitions = new UInt[nb_element_to_send + nb_ghost_element * 2]; AKANTU_DEBUG_INFO("Receiving partition informations from proc " << root); comm->receive(local_partitions, nb_element_to_send + nb_ghost_element * 2, root, TAG_PARTITIONS); AKANTU_DEBUG_INFO("Creating communications scheme"); communicator->fillCommunicationScheme(local_partitions, nb_local_element, nb_ghost_element, type); delete [] local_partitions; /* --------<<<<-TAGS------------------------------------------------- */ if(nb_tags) { AKANTU_DEBUG_INFO("Receiving associated data from proc " << root); UInt size_data = (nb_local_element + nb_ghost_element) * nb_tags + uint_names_size; local_data = new UInt[size_data]; comm->receive(local_data, size_data, root, TAG_DATA); MeshUtils::setUIntData(mesh, local_data, nb_tags, type); delete [] local_data; } } } while(type != _not_defined); /** * Nodes coordinate construction and synchronization on distant processors */ /* -------->>>>-NB_NODES + NODES----------------------------------------- */ AKANTU_DEBUG_INFO("Sending list of nodes to proc " << root); UInt nb_nodes = old_nodes->getSize(); comm->send(&nb_nodes, 1, root, TAG_NB_NODES); comm->send(old_nodes->values, nb_nodes, root, TAG_NODES); /* --------<<<<-COORDINATES---------------------------------------------- */ nodes->resize(nb_nodes); AKANTU_DEBUG_INFO("Receiving coordinates from proc " << root); comm->receive(nodes->values, nb_nodes * spatial_dimension, root, TAG_COORDINATES); communicator->fillNodesType(mesh); /* --------<<<<-NODES_TYPE-2--------------------------------------------- */ Int * nodes_types = mesh.getNodesTypePointer()->values; AKANTU_DEBUG_INFO("Sending first nodes types to proc " << root); comm->send(nodes_types, nb_nodes, root, TAG_NODES_TYPE); /* --------<<<<-NODES_TYPE-2--------------------------------------------- */ AKANTU_DEBUG_INFO("Receiving nodes types from proc " << root); comm->receive(nodes_types, nb_nodes, root, TAG_NODES_TYPE); } comm->broadcast(&(mesh.nb_global_nodes), 1, root); AKANTU_DEBUG_OUT(); return communicator; } /* -------------------------------------------------------------------------- */ void DistributedSynchronizer::fillNodesType(Mesh & mesh) { AKANTU_DEBUG_IN(); // StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); // UInt my_rank = comm->whoAmI(); UInt nb_nodes = mesh.getNbNodes(); // std::cout << nb_nodes << std::endl; Int * nodes_type = mesh.getNodesTypePointer()->values; //memcpy(nodes_type, nodes_type_tmp, nb_nodes * sizeof(Int)); UInt * nodes_set = new UInt[nb_nodes]; std::fill_n(nodes_set, nb_nodes, 0); Mesh::ConnectivityTypeList::const_iterator it; const UInt NORMAL_SET = 1; const UInt GHOST_SET = 2; bool * already_seen = new bool[nb_nodes]; - std::fill_n(already_seen, nb_nodes, false); - - const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(_not_ghost); - for(it = type_list.begin(); it != type_list.end(); ++it) { - ElementType type = *it; - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_element = mesh.getNbElement(type); - UInt * conn_val = mesh.getConnectivity(type).values; - - for (UInt e = 0; e < nb_element; ++e) { - for (UInt n = 0; n < nb_nodes_per_element; ++n) { - AKANTU_DEBUG_ASSERT(*conn_val < nb_nodes, "Node " << *conn_val << " bigger than number of nodes " << nb_nodes); - if(!already_seen[*conn_val]) { - nodes_set[*conn_val] += NORMAL_SET; - already_seen[*conn_val] = true; - } - conn_val++; - } - } - } - std::fill_n(already_seen, nb_nodes, false); - const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost); - for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { - ElementType type = *it; - UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); - UInt nb_element = mesh.getNbElement(type,_ghost); - UInt * conn_val = mesh.getConnectivity(type,_ghost).values; - - for (UInt e = 0; e < nb_element; ++e) { - for (UInt n = 0; n < nb_nodes_per_element; ++n) { - if(!already_seen[*conn_val]) { - nodes_set[*conn_val] += GHOST_SET; - already_seen[*conn_val] = true; + for(UInt g = _not_ghost; g <= _ghost; ++g) { + GhostType gt = (GhostType) g; + UInt set = NORMAL_SET; + if (gt == _ghost) set = GHOST_SET; + + std::fill_n(already_seen, nb_nodes, false); + const Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(gt); + for(it = type_list.begin(); it != type_list.end(); ++it) { + ElementType type = *it; + + UInt nb_nodes_per_element = Mesh::getNbNodesPerElement(type); + UInt nb_element = mesh.getNbElement(type, gt); + UInt * conn_val = mesh.getConnectivity(type, gt).values; + + for (UInt e = 0; e < nb_element; ++e) { + for (UInt n = 0; n < nb_nodes_per_element; ++n) { + AKANTU_DEBUG_ASSERT(*conn_val < nb_nodes, "Node " << *conn_val << " bigger than number of nodes " << nb_nodes); + if(!already_seen[*conn_val]) { + nodes_set[*conn_val] += set; + already_seen[*conn_val] = true; + } + conn_val++; } - conn_val++; } } } delete [] already_seen; for (UInt i = 0; i < nb_nodes; ++i) { if(nodes_set[i] == NORMAL_SET) nodes_type[i] = -1; else if(nodes_set[i] == GHOST_SET) nodes_type[i] = -3; else if(nodes_set[i] == (GHOST_SET + NORMAL_SET)) nodes_type[i] = -2; } delete [] nodes_set; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DistributedSynchronizer::fillCommunicationScheme(UInt * partition, UInt nb_local_element, UInt nb_ghost_element, ElementType type) { AKANTU_DEBUG_IN(); Element element; element.type = type; UInt * part = partition; part = partition; for (UInt lel = 0; lel < nb_local_element; ++lel) { UInt nb_send = *part; part++; element.element = lel; for (UInt p = 0; p < nb_send; ++p) { UInt proc = *part; part++; AKANTU_DEBUG(dblAccessory, "Must send : " << element << " to proc " << proc); (send_element[proc]).push_back(element); } } for (UInt gel = 0; gel < nb_ghost_element; ++gel) { UInt proc = *part; part++; element.element = gel; AKANTU_DEBUG(dblAccessory, "Must recv : " << element << " from proc " << proc); recv_element[proc].push_back(element); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DistributedSynchronizer::asynchronousSynchronize(DataAccessor & data_accessor, SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(send_requests.size() == 0, "There must be some pending sending communications. Tag is " << tag); if (size_to_send.count(tag) == 0 || size_to_receive.count(tag) == 0) computeBufferSize(data_accessor,tag); for (UInt p = 0; p < nb_proc; ++p) { UInt ssize = (size_to_send[tag]).values[p]; if(p == rank || ssize == 0) continue; CommunicationBuffer & buffer = send_buffer[p]; buffer.resize(ssize); Element * elements = &(send_element[p].at(0)); UInt nb_elements = send_element[p].size(); AKANTU_DEBUG_INFO("Packing data for proc " << p << " (" << ssize << "/" << nb_elements <<" data to send/elements)"); for (UInt el = 0; el < nb_elements; ++el) { data_accessor.packData(buffer, *elements, tag); elements++; } #ifndef AKANTU_NDEBUG // UInt block_size = data_accessor.getNbDataToPack(send_element[p][0], tag); // AKANTU_DEBUG_WARNING("tag is " << tag << ", packed buffer is " // << buffer.extractStream(block_size) // << std::endl); #endif AKANTU_DEBUG_ASSERT(buffer.getPackedSize() == ssize, "a problem have been introduced with " << "false sent sizes declaration " << buffer.getPackedSize() << " != " << ssize); std::cerr << std::dec; AKANTU_DEBUG_INFO("Posting send to proc " << p); send_requests.push_back(static_communicator->asyncSend(buffer.storage(), ssize, p, (Int) tag)); } AKANTU_DEBUG_ASSERT(recv_requests.size() == 0, "There must be some pending receive communications"); for (UInt p = 0; p < nb_proc; ++p) { UInt rsize = (size_to_receive[tag]).values[p]; if(p == rank || rsize == 0) continue; CommunicationBuffer & buffer = recv_buffer[p]; buffer.resize(rsize); AKANTU_DEBUG_INFO("Posting receive from proc " << p << " (" << rsize << " data to receive)"); recv_requests.push_back(static_communicator->asyncReceive(buffer.storage(), rsize, p, (Int) tag)); } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DistributedSynchronizer::waitEndSynchronize(DataAccessor & data_accessor, SynchronizationTag tag) { AKANTU_DEBUG_IN(); std::vector req_not_finished; std::vector * req_not_finished_tmp = &req_not_finished; std::vector * recv_requests_tmp = &recv_requests; static_communicator->waitAll(recv_requests); while(!recv_requests_tmp->empty()) { for (std::vector::iterator req_it = recv_requests_tmp->begin(); req_it != recv_requests_tmp->end() ; ++req_it) { CommunicationRequest * req = *req_it; if(static_communicator->testRequest(req)) { UInt proc = req->getSource(); AKANTU_DEBUG_INFO("Unpacking data coming from proc " << proc); CommunicationBuffer & buffer = recv_buffer[proc]; Element * elements = &recv_element[proc].at(0); UInt nb_elements = recv_element[proc].size(); UInt el = 0; try { for (el = 0; el < nb_elements; ++el) { data_accessor.unpackData(buffer, *elements, tag); elements++; } } catch (debug::Exception & e){ UInt block_size = data_accessor.getNbDataToPack(recv_element[proc][0], tag); AKANTU_DEBUG_ERROR("catched exception during unpack from proc " << proc << " buffer index is " << el << "/" << nb_elements << std::endl << e.what() << std::endl << "buffer size " << buffer.getSize() << std::endl << buffer.extractStream(block_size)); } AKANTU_DEBUG_ASSERT(buffer.getLeftToUnpack() == 0, "all data have not been unpacked: " << buffer.getLeftToUnpack() << " bytes left"); static_communicator->freeCommunicationRequest(req); } else { req_not_finished_tmp->push_back(req); } } std::vector * swap = req_not_finished_tmp; req_not_finished_tmp = recv_requests_tmp; recv_requests_tmp = swap; req_not_finished_tmp->clear(); } static_communicator->waitAll(send_requests); static_communicator->freeCommunicationRequest(send_requests); send_requests.clear(); AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void DistributedSynchronizer::computeBufferSize(DataAccessor & data_accessor, SynchronizationTag tag) { AKANTU_DEBUG_IN(); AKANTU_DEBUG_ASSERT(size_to_send.find(tag) == size_to_send.end(), "The SynchronizationTag< " << tag << "is already registered in " << id); size_to_send [tag].resize(nb_proc); size_to_receive[tag].resize(nb_proc); for (UInt p = 0; p < nb_proc; ++p) { UInt ssend = 0; UInt sreceive = 0; if(p != rank) { for (std::vector::const_iterator sit = send_element[p].begin(); sit != send_element[p].end(); ++sit) { ssend += data_accessor.getNbDataToPack(*sit, tag); } for (std::vector::const_iterator rit = recv_element[p].begin(); rit != recv_element[p].end(); ++rit) { sreceive += data_accessor.getNbDataToUnpack(*rit, tag); } AKANTU_DEBUG_INFO("I have " << ssend << "(" << ssend / 1024. << "kB) data to send to " << p << " and " << sreceive << "(" << ssend / 1024. << "kB) data to receive for tag " << tag); } size_to_send [tag].values[p] = ssend; size_to_receive[tag].values[p] = sreceive; } AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/synchronizer/static_communicator_inline_impl.cc b/synchronizer/static_communicator_inline_impl.cc index 8c54bc8fa..76991f8db 100644 --- a/synchronizer/static_communicator_inline_impl.cc +++ b/synchronizer/static_communicator_inline_impl.cc @@ -1,152 +1,150 @@ /** * @file static_communicator_inline_impl.cc * @author Nicolas Richart * @date Mon Sep 6 00:16:19 2010 * * @brief implementation of inline functions * * @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 . * */ /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::freeCommunicationRequest(CommunicationRequest * request) { delete request; } /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::freeCommunicationRequest(std::vector & requests) { std::vector::iterator it; for(it = requests.begin(); it != requests.end(); ++it) { delete (*it); } } #if defined(__INTEL_COMPILER) #pragma warning ( push ) #pragma warning ( disable : 111 ) #endif //defined(__INTEL_COMPILER) /* -------------------------------------------------------------------------- */ #define AKANTU_BOOST_REAL_COMMUNICATOR_CALL(r, call, comm_type) \ case BOOST_PP_LIST_AT(comm_type, 0): { \ BOOST_PP_LIST_AT(comm_type, 1) * comm = \ dynamic_cast(real_static_communicator); \ BOOST_PP_IF(BOOST_PP_LIST_AT(call, 0), \ return comm->BOOST_PP_LIST_AT(call, 1), \ comm->BOOST_PP_LIST_AT(call, 1)); \ break; \ } #define AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(call, ret) \ do { \ switch(real_type) \ { \ BOOST_PP_SEQ_FOR_EACH(AKANTU_BOOST_REAL_COMMUNICATOR_CALL, \ (ret, (call, BOST_PP_NIL)), \ AKANTU_COMMUNICATOR_LIST_ALL) \ - default: \ - AKANTU_DEBUG_TO_IMPLEMENT(); \ } \ } while(0) /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::send(T * buffer, Int size, Int receiver, Int tag) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(send(buffer, size, receiver, tag), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::receive(T * buffer, Int size, Int sender, Int tag) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(receive(buffer, size, sender, tag), 0); } /* -------------------------------------------------------------------------- */ template inline CommunicationRequest * StaticCommunicator::asyncSend(T * buffer, Int size, Int receiver, Int tag) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(asyncSend(buffer, size, receiver, tag), 1); return NULL; } /* -------------------------------------------------------------------------- */ template inline CommunicationRequest * StaticCommunicator::asyncReceive(T * buffer, Int size, Int sender, Int tag) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(asyncReceive(buffer, size, sender, tag), 1); return NULL; } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::allReduce(T * values, Int nb_values, const SynchronizerOperation & op) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(allReduce(values, nb_values, op), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::allGather(T * values, Int nb_values) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(allGather(values, nb_values), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::allGatherV(T * values, Int * nb_values) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(allGatherV(values, nb_values), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::gather(T * values, Int nb_values, Int root) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(gather(values, nb_values, root), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::gatherV(T * values, Int * nb_values, Int root) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(gatherV(values, nb_values, root), 0); } /* -------------------------------------------------------------------------- */ template inline void StaticCommunicator::broadcast(T * values, Int nb_values, Int root) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(broadcast(values, nb_values, root), 0); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::barrier() { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(barrier(), 0); } /* -------------------------------------------------------------------------- */ inline bool StaticCommunicator::testRequest(CommunicationRequest * request) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(testRequest(request), 1); return false; } /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::wait(CommunicationRequest * request) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(wait(request), 0); } /* -------------------------------------------------------------------------- */ inline void StaticCommunicator::waitAll(std::vector & requests) { AKANTU_BOOST_REAL_COMMUNICATOR_SELECT_CALL(waitAll(requests), 0); } #if defined(__INTEL_COMPILER) #pragma warning ( pop ) #endif //defined(__INTEL_COMPILER) diff --git a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc index cc3f1e9f1..b324a32ca 100644 --- a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc +++ b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d.cc @@ -1,183 +1,180 @@ /** * @file test_heat_transfer_model_cube3d.cc * @author Rui WANG * @date Tue May 17 11:31:22 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; /* -------------------------------------------------------------------------- */ void paraviewInit(HeatTransferModel * model,Dumper & dumper); void paraviewDump(Dumper & dumper); UInt spatial_dimension = 3; ElementType type = _tetrahedron_4; UInt paraview_type = TETRA1; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(&argc,&argv); Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("cube1.msh", mesh); HeatTransferModel * model; UInt nb_nodes; UInt nb_element; model = new HeatTransferModel(mesh); model->readMaterials("material.dat"); //model initialization model->initModel(); //initialize the vectors model->initVectors(); nb_nodes = mesh.getNbNodes(); nb_element = mesh.getNbElement(type); nb_nodes = mesh.getNbNodes(); - model->getResidual().clear(); model->getTemperature().clear(); model->getTemperatureRate().clear(); - model->getCapacityLumped().clear(); - model->getTemperatureGradient(type).clear(); //get stable time step Real time_step = model->getStableTimeStep()*0.8; std::cout << "time step is:" << time_step << std::endl; model->setTimeStep(time_step); /// boundary conditions const Vector & nodes = mesh.getNodes(); Vector & boundary = model->getBoundary(); Vector & temperature = model->getTemperature(); double t1, t2, length; t1 = 300.; t2 = 100.; length = 1.; for (UInt i = 0; i < nb_nodes; ++i) { //temperature(i) = t1 - (t1 - t2) * sin(nodes(i, 0) * M_PI / length); temperature(i) = 100.; // if(nodes(i,0) < eps) { // boundary(i) = true; // temperature(i) = 100.0; // } //set the second boundary condition // if(std::abs(nodes(i,0) - length) < eps) { // boundary(i) = true; // temperature(i) = 100.; // } //to insert a heat source Real dx = nodes(i,0) - length/2.; Real dy = nodes(i,1) - length/2.; Real dz = nodes(i,2) - length/2.; Real d = sqrt(dx*dx + dy*dy + dz*dz); if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } DumperParaview dumper; paraviewInit(model,dumper); model->assembleCapacityLumped(); // //for testing - int max_steps = 100000; + int max_steps = 1000; for(int i=0; iexplicitPred(); model->updateResidual(); model->solveExplicitLumped(); model->explicitCorr(); if(i % 100 == 0) paraviewDump(dumper); if(i % 10 == 0) std::cout << "Step " << i << "/" << max_steps << std::endl; } std::cout << "Stable Time Step is : " << time_step << std::endl; return 0; } /* -------------------------------------------------------------------------- */ void paraviewInit(HeatTransferModel * model, Dumper & dumper) { Mesh & mesh = model->getFEM().getMesh(); UInt nb_nodes = mesh.getNbNodes(); UInt nb_element = mesh.getNbElement(type); dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "coordinates2"); dumper.SetConnectivity((int *) mesh.getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getTemperature().values, 1, "temperature"); dumper.AddNodeDataField(model->getTemperatureRate().values, 1, "temperature_rate"); dumper.AddNodeDataField(model->getResidual().values, 1, "residual"); dumper.AddNodeDataField(model->getCapacityLumped().values, 1, "capacity_lumped"); dumper.AddElemDataField(model->getTemperatureGradient(type).values, spatial_dimension, "temperature_gradient"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { dumper.Dump(); } /* -------------------------------------------------------------------------- */ diff --git a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_istropic_conductivity.cc b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_istropic_conductivity.cc index 6ccaa6a59..56310c846 100644 --- a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_istropic_conductivity.cc +++ b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_istropic_conductivity.cc @@ -1,178 +1,180 @@ /** * @file test_heat_transfer_model_cube3d_istropic_conductivity.cc * @author Rui WANG * @date Tue May 17 11:31:22 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" //#include "material.hh" // basic file operations #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER akantu::UInt spatial_dimension = 3; akantu:: ElementType type = akantu::_tetrahedron_4; akantu::UInt paraview_type = TETRA1; //just for checking void paraviewInit(Dumper & dumper); void paraviewDump(Dumper & dumper); akantu::HeatTransferModel * model; akantu::UInt nb_nodes; akantu::UInt nb_element; int main(int argc, char *argv[]) { + akantu::initialize(&argc, &argv); + akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("cube1.msh", mesh); model = new akantu::HeatTransferModel(mesh); model->readMaterials("material.dat"); //model initialization model->initModel(); //initialize the vectors model->initVectors(); nb_nodes = model->getFEM().getMesh().getNbNodes(); nb_element = model->getFEM().getMesh().getNbElement(type); akantu::UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); - model->getResidual().clear(); + model->getTemperature().clear(); model->getTemperatureRate().clear(); - model->getCapacityLumped().clear(); - model->getTemperatureGradient(type).clear(); + + //get stable time step akantu::Real time_step = model->getStableTimeStep()*0.8; cout<<"time step is:"<setTimeStep(time_step); /// boundary conditions const akantu::Vector & nodes = model->getFEM().getMesh().getNodes(); akantu::Vector & boundary = model->getBoundary(); akantu::Vector & temperature = model->getTemperature(); akantu::Real eps = 1e-15; double length = 1.; for (akantu::UInt i = 0; i < nb_nodes; ++i) { //temperature(i) = t1 - (t1 - t2) * sin(nodes(i, 0) * M_PI / length); temperature(i) = 100.; if(nodes(i,0) < eps) { boundary(i) = true; temperature(i) = 300.; } //set the second boundary condition if(std::abs(nodes(i,0) - length) < eps) { boundary(i) = true; temperature(i) = 300.; } // //to insert a heat source // if(std::abs(nodes(i,0) - length/2.) < 0.025 && std::abs(nodes(i,1) - length/2.) < 0.025 && std::abs(nodes(i,2) - length/2.) < 0.025) { // boundary(i) = true; // temperature(i) = 300.; // } } DumperParaview dumper; paraviewInit(dumper); model->assembleCapacityLumped(); // //for testing - int max_steps = 100000; + int max_steps = 1000; for(int i=0; iexplicitPred(); model->updateResidual(); model->solveExplicitLumped(); model->explicitCorr(); if(i % 100 == 0) paraviewDump(dumper); if(i % 10000 == 0) std::cout << "Step " << i << "/" << max_steps << std::endl; } cout<< "\n\n Stable Time Step is : " << time_step << "\n \n" <getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates_cube3d_istropic_conductivity"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getTemperature().values, 1, "temperature"); dumper.AddNodeDataField(model->getResidual().values, 1, "residual"); dumper.AddNodeDataField(model->getTemperatureRate().values, 1, "temperature_rate"); dumper.AddNodeDataField(model->getCapacityLumped().values, 1, "capacity"); dumper.AddElemDataField(model->getTemperatureGradient(type).values, spatial_dimension, "temperature_gradient"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } void paraviewDump(Dumper & dumper) { dumper.Dump(); } diff --git a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_pbc.cc b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_pbc.cc index 638504a36..55bfb51ae 100644 --- a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_pbc.cc +++ b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_cube3d_pbc.cc @@ -1,177 +1,174 @@ /** * @file test_heat_transfer_model_cube3d.cc * @author Rui WANG * @date Tue May 17 11:31:22 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" #include "pbc_synchronizer.hh" #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER void paraviewInit(akantu::HeatTransferModel * model,Dumper & dumper); void paraviewDump(Dumper & dumper); akantu::UInt spatial_dimension = 3; akantu:: ElementType type = akantu::_tetrahedron_4; akantu::UInt paraview_type = TETRA1; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc,&argv); akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("cube_tet4.msh", mesh); akantu::HeatTransferModel * model; akantu::UInt nb_nodes; akantu::UInt nb_element; model = new akantu::HeatTransferModel(mesh); /* -------------------------------------------------------------------------- */ model->readMaterials("material.dat"); model->initModel(); model->initVectors(); - model->getResidual().clear(); model->getTemperature().clear(); model->getTemperatureRate().clear(); - model->getCapacityLumped().clear(); - model->getTemperatureGradient(type).clear(); /* -------------------------------------------------------------------------- */ model->initPBC(1,1,1); model->assembleCapacityLumped(); /* -------------------------------------------------------------------------- */ nb_nodes = model->getFEM().getMesh().getNbNodes(); nb_element = model->getFEM().getMesh().getNbElement(type); nb_nodes = model->getFEM().getMesh().getNbNodes(); /* ------------------------------------------------------------------------ */ //get stable time step akantu::Real time_step = model->getStableTimeStep()*0.8; cout<<"time step is:"<setTimeStep(time_step); /* -------------------------------------------------------------------------- */ /// boundary conditions const akantu::Vector & nodes = model->getFEM().getMesh().getNodes(); akantu::Vector & boundary = model->getBoundary(); akantu::Vector & temperature = model->getTemperature(); double t1, t2, length; t1 = 300.; t2 = 100.; length = 1.; for (akantu::UInt i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; akantu::Real dx = nodes(i,0) - length/4.; akantu::Real dy = nodes(i,1) - length/4.; akantu::Real dz = nodes(i,2) - length/4.; akantu::Real d = sqrt(dx*dx + dy*dy + dz*dz); if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } /* -------------------------------------------------------------------------- */ DumperParaview dumper; paraviewInit(model,dumper); /* ------------------------------------------------------------------------ */ // //for testing - int max_steps = 3000; + int max_steps = 1000; /* ------------------------------------------------------------------------ */ for(int i=0; iexplicitPred(); model->updateResidual(); model->solveExplicitLumped(); model->explicitCorr(); if(i % 100 == 0) paraviewDump(dumper); if(i % 10 == 0) std::cout << "Step " << i << "/" << max_steps << std::endl; } cout<< "\n\n Stable Time Step is : " << time_step << "\n \n" <getFEM().getMesh().getNbNodes(); akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates2"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getTemperature().values, 1, "temperature"); dumper.AddNodeDataField(model->getResidual().values, 1, "residual"); dumper.AddNodeDataField(model->getCapacityLumped().values, 1, "capacity_lumped"); // dumper.AddElemDataField(model->getTemperatureGradient(type).values, // spatial_dimension, "temperature_gradient"); // dumper.AddElemDataField(model->getbtkgt().values, // 4, "btkgt"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { dumper.Dump(); } /* -------------------------------------------------------------------------- */ diff --git a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_square2d_pbc.cc b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_square2d_pbc.cc index 481ab4e19..4c24dce47 100644 --- a/test/test_model/test_heat_transfer_model/test_heat_transfer_model_square2d_pbc.cc +++ b/test/test_model/test_heat_transfer_model/test_heat_transfer_model_square2d_pbc.cc @@ -1,183 +1,180 @@ /** * @file test_heat_transfer_model_cube3d.cc * @author Rui WANG * @date Tue May 17 11:31:22 2011 * * @brief test of the class HeatTransferModel on the 3d cube * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "heat_transfer_model.hh" #include "pbc_synchronizer.hh" #include #include #include using namespace std; /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER void paraviewInit(akantu::HeatTransferModel * model,Dumper & dumper); void paraviewDump(Dumper & dumper); akantu::UInt spatial_dimension = 2; akantu:: ElementType type = akantu::_triangle_3; akantu::UInt paraview_type = TRIANGLE1; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::debug::setDebugLevel(akantu::dblWarning); akantu::initialize(&argc,&argv); akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("square_tri3.msh", mesh); akantu::HeatTransferModel * model; akantu::UInt nb_nodes; akantu::UInt nb_element; model = new akantu::HeatTransferModel(mesh); /* -------------------------------------------------------------------------- */ model->readMaterials("material.dat"); model->initModel(); model->initVectors(); - model->getResidual().clear(); model->getTemperature().clear(); model->getTemperatureRate().clear(); - model->getCapacityLumped().clear(); - model->getTemperatureGradient(type).clear(); /* -------------------------------------------------------------------------- */ model->initPBC(1,1,1); model->assembleCapacityLumped(); /* -------------------------------------------------------------------------- */ nb_nodes = model->getFEM().getMesh().getNbNodes(); nb_element = model->getFEM().getMesh().getNbElement(type); nb_nodes = model->getFEM().getMesh().getNbNodes(); /* ------------------------------------------------------------------------ */ //get stable time step akantu::Real time_step = model->getStableTimeStep()*0.8; cout<<"time step is:"<setTimeStep(time_step); /* -------------------------------------------------------------------------- */ /// boundary conditions const akantu::Vector & nodes = model->getFEM().getMesh().getNodes(); akantu::Vector & boundary = model->getBoundary(); akantu::Vector & temperature = model->getTemperature(); double t1, t2, length; t1 = 300.; t2 = 100.; length = 1.; for (akantu::UInt i = 0; i < nb_nodes; ++i) { temperature(i) = 100.; akantu::Real dx = nodes(i,0) - length/4.; akantu::Real dy = 0.0; akantu::Real dz = 0.0; if (spatial_dimension > 1) dy = nodes(i,1) - length/4.; if (spatial_dimension == 3) dz = nodes(i,2) - length/4.; akantu::Real d = sqrt(dx*dx + dy*dy + dz*dz); // if(dx < 0.0){ if(d < 0.1){ boundary(i) = true; temperature(i) = 300.; } } /* -------------------------------------------------------------------------- */ DumperParaview dumper; paraviewInit(model,dumper); /* ------------------------------------------------------------------------ */ // //for testing int max_steps = 100000; /* ------------------------------------------------------------------------ */ for(int i=0; iexplicitPred(); model->updateResidual(); model->solveExplicitLumped(); model->explicitCorr(); if(i % 100 == 0) paraviewDump(dumper); if(i % 10 == 0) std::cout << "Step " << i << "/" << max_steps << std::endl; } cout<< "\n\n Stable Time Step is : " << time_step << "\n \n" <getFEM().getMesh().getNbNodes(); akantu::UInt nb_element = model->getFEM().getMesh().getNbElement(type); dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, "coordinates2"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getTemperature().values, 1, "temperature"); dumper.AddNodeDataField(model->getTemperatureRate().values, 1, "temperature_rate"); dumper.AddNodeDataField(model->getResidual().values, 1, "residual"); dumper.AddNodeDataField(model->getCapacityLumped().values, 1, "capacity_lumped"); dumper.AddElemDataField(model->getTemperatureGradient(type).values, spatial_dimension, "temperature_gradient"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { dumper.Dump(); } /* -------------------------------------------------------------------------- */ diff --git a/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt index 054143126..d7f616017 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/CMakeLists.txt @@ -1,35 +1,35 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Fri Dec 03 11:09:59 2010 # # @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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== -add_subdirectory("test_neighbor_structure") -add_subdirectory("test_contact_search") -add_subdirectory("test_contact_2d") -add_subdirectory("test_contact_rigid") -add_subdirectory("test_friction_coefficient") +add_akantu_test(test_neighbor_structure "test_neighbor_structure") +add_akantu_test(test_contact_search "test_contact_search") +add_akantu_test(test_contact_2d "test_contact_2d") +add_akantu_test(test_contact_rigid "test_contact_rigid") +add_akantu_test(test_friction_coefficient "test_friction_coefficient") diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt index e774fe1b7..0f7c9afc4 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/CMakeLists.txt @@ -1,32 +1,35 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi # @date Fri Dec 3 15:12:22 2010 # # @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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_contact_2d_expli_mesh squares.geo 2 1) register_test(test_contact_2d_expli test_contact_2d_expli.cc) add_dependencies(test_contact_2d_expli test_contact_2d_expli_mesh) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) +file(COPY materials.dat DESTINATION .) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc index 96973c188..f599c2a60 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_2d/test_contact_2d_expli/test_contact_2d_expli.cc @@ -1,270 +1,270 @@ /** * @file test_contact_2d_expli.cc * @author Leonardo Snozzi * @date Fri Nov 26 07:43:47 2010 * * @brief test explicit DCR contact algorithm for 2d * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_2d_explicit.hh" #include "io_helper.h" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER #include "io_helper.h" #endif //AKANTU_USE_IOHELPER #define NORMAL_PRESSURE -1.e6 using namespace akantu; static void reduceGap(const SolidMechanicsModel & model, const Real threshold, const Real gap); static void setBoundaryConditions(SolidMechanicsModel & model); void my_force(double * coord, double *T); static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio); static void initParaview(SolidMechanicsModel & model); Real y_min, y_max; DumperParaview dumper; int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); UInt spatial_dimension = 2; UInt max_steps = 30000; Real time_factor = 0.2; Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// get two squares closer // reduceGap(*model, 0.05, 1.e-6); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); UInt nb_elements = model->getFEM().getMesh().getNbElement(_triangle_3); /// model initialization + model->initModel(); model->initVectors(); model->readMaterials("materials.dat"); model->initMaterials(); - - model->initModel(); + model->initExplicit(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// set vectors to zero memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getMaterial(0).getStrain(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); memset(model->getMaterial(0).getStress(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); /// Paraview Helper #ifdef AKANTU_USE_IOHELPER initParaview(*model); #endif //AKANTU_USE_IOHELPER Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /// set boundary conditions setBoundaryConditions(*model); /// define and initialize contact Contact * contact = Contact::newContact(*model, _ct_2d_expli, _cst_2d_expli, _cnst_2d_grid); Contact2dExplicit * my_contact = dynamic_cast(contact); my_contact->initContact(true); my_contact->setFrictionCoefficient(0.); my_contact->initNeighborStructure(); my_contact->initSearch(); for (UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateCurrentPosition(); my_contact->solveContact(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); if(s % 200 == 0) dumper.Dump(); if(s%100 == 0 && s>499) reduceVelocities(*model, 0.95); if(s % 500 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } delete my_contact; delete model; finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ static void reduceGap(const SolidMechanicsModel & model, const Real threshold, const Real gap) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; Real y_top = HUGE_VAL, y_bot = -HUGE_VAL; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) { if(coord[2*n+1] < y_top) y_top = coord[2*n+1]; } else { if (coord[2*n+1] > y_bot) y_bot = coord[2*n+1]; } } Real delta = y_top - y_bot - gap; /// move all nodes belonging to the top cube for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > threshold) coord[2*n+1] -= delta; } } /* -------------------------------------------------------------------------- */ static void setBoundaryConditions(SolidMechanicsModel & model) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * coord = model.getFEM().getMesh().getNodes().values; for (UInt n = 0; n < nb_nodes; ++n) { if (coord[2*n+1] > y_max) y_max = coord[2*n+1]; if (coord[2*n+1] < y_min) y_min = coord[2*n+1]; } FEM & b_fem = model.getFEMBoundary(); b_fem.initShapeFunctions(); b_fem.computeNormalsOnControlPoints(); bool * id = model.getBoundary().values; memset(id, 0, 2*nb_nodes*sizeof(bool)); std::cout << "Nodes "; for (UInt i = 0; i < nb_nodes; ++i) { if (coord[2*i+1] < y_min + 1.e-5) { id[2*i+1] = true; std::cout << " " << i << " "; } } std::cout << "are blocked" << std::endl; model.computeForcesFromFunction(my_force, _bft_stress); } /* -------------------------------------------------------------------------- */ void my_force(double * coord, double *T) { memset(T, 0, 4*sizeof(double)); if(*(coord+1) > y_max-1.e-5) T[3] = NORMAL_PRESSURE; } /* -------------------------------------------------------------------------- */ /// artificial damping of velocities in order to reach a global static equilibrium static void reduceVelocities(const SolidMechanicsModel & model, const Real ratio) { UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); Real * velocities = model.getVelocity().values; if(ratio>1.) { fprintf(stderr,"**error** in Reduce_Velocities ratio bigger than 1!\n"); exit(-1); } for(UInt i =0; i * @date Mon Jan 24 10:04:42 2011 * * @brief test for force in 2d rigid contact in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 2; const ElementType element_type = _triangle_3; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TRIANGLE1; #endif //AKANTU_USE_IOHELPER akantu::initialize(&argc, &argv); UInt imposing_steps = 1000; Real max_displacement = -0.01; UInt damping_steps = 80000; UInt damping_interval = 50; Real damping_ratio = 0.985; UInt max_steps = damping_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("force_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.19999) { boundary[node*dim] = true; boundary[node*dim + 1] = true; } } UInt * top_nodes_val = top_nodes->values; Real * velocity_val = my_model.getVelocity().values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_force_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/force_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream force_out; force_out.open("output_files/force_2d.csv"); force_out << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s == imposing_steps){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s < damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; /* // find index of master surface in impactors_information Int master_index = -1; for (UInt i=0; i < my_contact->getImpactorsInformation().size(); ++i) { if (my_contact->getImpactorsInformation().at(i)->master_id == master) { master_index = i; break; } } // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = my_contact->getImpactorsInformation().at(master_index); */ // find the total contact force and contact area UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } force_out << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; // test if correct result is found if((s == max_steps) && (std::abs(top_force - 2.30769e+09) > 1e4)) { std::cout << "top_force = " << top_force << " but should be = 2.30769e+09" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 1000 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } force_out.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_force_3d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_force_3d.cc index 3d272cff2..a6f96feab 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_force_3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_force_3d.cc @@ -1,284 +1,284 @@ /** * @file test_contact_rigid_no_friction_force_3d.cc * @author David Kammer * @date Mon Jan 24 11:56:42 2011 * * @brief test force for rigid contact 3d in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; const ElementType element_type = _tetrahedron_4; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TETRA1; #endif //AKANTU_USE_IOHELPER akantu::initialize(&argc, &argv); UInt imposing_steps = 1000; Real max_displacement = -0.01; UInt damping_steps = 80000; UInt damping_interval = 50; Real damping_ratio = 0.985; UInt max_steps = damping_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("force_3d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); Real * velocity_val = my_model.getVelocity().values; Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); //UInt * connectivity = my_mesh.getConnectivity(surface_element_type).values; //UInt nb_nodes_elem = Mesh::getNbNodesPerElement(surface_element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); // Surface master = 1; my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.19999) { boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } } UInt * top_nodes_val = top_nodes->values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_force_3d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/force_3d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream force_out; force_out.open("output_files/force_3d.csv"); force_out << "%id,ftop,fcont,zone" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s == imposing_steps){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s < damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } force_out << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; // test if correct result is found if((s == max_steps) && (std::abs(top_force - 2.1e+09) > 1e4)) { std::cout << "top_force = " << top_force << " but should be = 2.1e+09" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); my_model.explicitCorr(); #ifdef AKANTU_USE_IOHELPER if(s % 1000 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } force_out.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_2d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_2d.cc index 4ef9f1460..ec6af8523 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_2d.cc @@ -1,297 +1,297 @@ /** * @file test_contact_rigid_no_friction_hertz_2d.cc * @author David Kammer * @date Wed Jan 19 15:04:42 2011 * * @brief test contact search for 2d hertz in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 2; const ElementType element_type = _triangle_3; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TRIANGLE1; #endif //AKANTU_USE_IOHELPER akantu::initialize(&argc, &argv); UInt imposing_steps = 1000; Real max_displacement = -0.01; UInt damping_steps = 75000; UInt damping_interval = 50; Real damping_ratio = 0.99; UInt max_steps = damping_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("hertz_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); //Surface master = 1; my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; if (x_coord < 0.00001) boundary[node*dim] = true; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.199999) { boundary[node*dim] = true; boundary[node*dim + 1] = true; } } UInt * top_nodes_val = top_nodes->values; Real * velocity_val = my_model.getVelocity().values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/hertz_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream hertz; hertz.open("output_files/hertz_2d.csv"); hertz << "%id,ftop,fcont,zone" << std::endl; std::ofstream energy; energy.open("output_files/hertz_2d_energy.csv"); energy << "%id,kin,pot,tot" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 200 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s < damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } hertz << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; // test if correct result is found if((s == max_steps) && (std::abs(contact_zone - 0.0540056) > 1e-7)) { std::cout << "contact_zone = " << contact_zone << " but should be = 0.0540056" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); my_model.explicitCorr(); Real epot = my_model.getPotentialEnergy(); Real ekin = my_model.getKineticEnergy(); energy << s << "," << ekin << "," << epot << "," << ekin+epot << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } hertz.close(); energy.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_3d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_3d.cc index 2ba35b106..48ff63718 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_no_friction_hertz_3d.cc @@ -1,301 +1,301 @@ /** * @file test_contact_rigid_no_friction_hertz_3d.cc * @author David Kammer * @date Thu Jan 20 15:50:42 2011 * * @brief test rigid contact for 3d hertz in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; const ElementType element_type = _tetrahedron_4; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TETRA1; #endif //AKANTU_USE_IOHELPER akantu::initialize(&argc, &argv); UInt imposing_steps = 1000; Real max_displacement = -0.01; UInt damping_steps = 75000; UInt damping_interval = 50; Real damping_ratio = 0.99; UInt max_steps = damping_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("hertz_3d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; Real z_coord = coordinates[node*dim + 2]; if (x_coord < 0.00001) boundary[node*dim] = true; if (z_coord < 0.00001) boundary[node*dim+2] = true; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.19999) { boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } } UInt * top_nodes_val = top_nodes->values; Real * velocity_val = my_model.getVelocity().values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coordinates_3d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/hertz_3d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream hertz; hertz.open("output_files/hertz_3d.csv"); hertz << "%id,ftop,fcont,zone" << std::endl; std::ofstream energy; energy.open("output_files/hertz_3d_energy.csv"); energy << "%id,kin,pot,tot" << std::endl; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; /* if(s % 250 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } */ if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s < damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real * current_position = my_model.getCurrentPosition().values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } hertz << s << "," << top_force << "," << contact_force << "," << contact_zone << std::endl; // test if correct result is found if((s == max_steps) && (std::abs(contact_force + 7.29637e+07) > 1e2)) { std::cout << "contact_force = " << contact_force << " but should be = -7.29637e+07" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); my_model.explicitCorr(); Real epot = my_model.getPotentialEnergy(); Real ekin = my_model.getKineticEnergy(); energy << s << "," << ekin << "," << epot << "," << ekin+epot << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } hertz.close(); energy.close(); delete my_contact; delete top_nodes; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_2d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_2d.cc index 867d37b73..675fe6af9 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_2d.cc @@ -1,358 +1,358 @@ /** * @file test_contact_rigid_sliding_cube_2d.cc * @author David Kammer * @date Tue Feb 08 15:56:42 2011 * * @brief test rigid contact for a 2d sliding cube in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "friction_coefficient.hh" #include "unique_constant_fric_coef.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); UInt dim = 2; const ElementType element_type = _triangle_3; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TRIANGLE1; #endif //AKANTU_USE_IOHELPER //UInt max_steps = 200000; UInt imposing_steps = 20000; Real max_displacement = -0.01; UInt damping_steps = 10000; UInt damping_interval = 100; Real damping_ratio = 0.5; Real imposed_velocity = 401.92; Real needed_time = 0.005; UInt additional_steps = 2000; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("sliding_cube_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initExplicit(); my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); //my_model.readMaterials("material.dat"); my_model.readMaterials("material_elastic_caughey.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); UInt max_steps = static_cast(needed_time*10/time_step) + imposing_steps + damping_steps + additional_steps; std::cout << "The number of time steps is found to be: " << max_steps << std::endl; Real * velocity_val = my_model.getVelocity().values; Real * acceleration_val = my_model.getAcceleration().values; my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); UniqueConstantFricCoef * fric_coef = new UniqueConstantFricCoef(*my_contact, master, 0.3); //my_contact->setFrictionCoefficient(fric_coef); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // symetry boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.49) boundary[node*dim] = true; boundary[node*dim + 1] = true; } UInt * top_nodes_val = top_nodes->values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coord_sliding_cube_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/sliding_cube_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream out_info; out_info.open("output_files/sliding_cube_2d.csv"); out_info << "%id,ftop,fcont,zone,stickNode,contNode" << std::endl; std::ofstream energy; energy.open("output_files/sliding_cube_2d_energy.csv"); energy << "%id,kin,pot,tot" << std::endl; Real * current_position = my_model.getCurrentPosition().values; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) { std::cout << "passing step " << s << "/" << max_steps << "\r"; std::cout.flush(); } if(s % 20000 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } // impose normal displacement if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s > imposing_steps && s < imposing_steps+damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } // give initial velocity if(s == imposing_steps+damping_steps) { ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; bool * stick = imp_info->node_is_sticking->values; Real * p_vel = imp_info->previous_velocities->values; for(UInt i=0; i < imp_info->active_impactor_nodes->getSize(); ++i) { stick[i*2] = false; stick[i*2+1] = false; p_vel[i*dim + 0] = imposed_velocity; } /*for (UInt i=0; i < nb_nodes; ++i) { if(coordinates[i*dim + 1] > -1) { velocity_val[i*dim] = imposed_velocity; } }*/ UInt * connectivity = my_mesh.getConnectivity(element_type).values; UInt nb_nodes_elem = Mesh::getNbNodesPerElement(element_type); for(UInt i=0; i < nb_element; ++i) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,element_type,barycenter_p); if(barycenter_p[1] > -1) { for (UInt j=0; j < nb_nodes_elem; ++j) { velocity_val[connectivity[i*nb_nodes_elem+j]*dim] = imposed_velocity; acceleration_val[connectivity[i*nb_nodes_elem +j]*dim] = 0.; } } } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); my_contact->frictionPredictor(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } out_info << s << "," << top_force << "," << contact_force << "," << contact_zone << ","; // test if correct result is found if((s == max_steps) && (std::abs(contact_zone - 1.8988) > 1e-4)) { std::cout << "sliding distance = " << contact_zone << " but should be = 1.8988" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); const Vector * sticking_nodes = imp_info->node_is_sticking; bool * sticking_nodes_val = sticking_nodes->values; UInt nb_sticking_nodes = 0; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { if(sticking_nodes_val[i*2]) nb_sticking_nodes++; } out_info << nb_sticking_nodes << "," << imp_info->active_impactor_nodes->getSize() << std::endl; my_model.explicitCorr(); my_contact->frictionCorrector(); Real epot = my_model.getPotentialEnergy(); Real ekin = my_model.getKineticEnergy(); energy << s << "," << ekin << "," << epot << "," << ekin+epot << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } out_info.close(); energy.close(); delete fric_coef; delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_3d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_3d.cc index 337928a46..228d5c425 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_3d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_contact_rigid/test_contact_rigid_sliding_cube_3d.cc @@ -1,346 +1,346 @@ /** * @file test_contact_rigid_sliding_cube_3d.cc * @author David Kammer * @date Mon Feb 14 10:56:42 2011 * * @brief test rigid contact for a 3d sliding cube in explicit * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "friction_coefficient.hh" #include "unique_constant_fric_coef.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { UInt dim = 3; const ElementType element_type = _tetrahedron_4; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TETRA1; #endif //AKANTU_USE_IOHELPER akantu::initialize(&argc, &argv); //UInt max_steps = 200000; UInt imposing_steps = 20000; Real max_displacement = -0.01; UInt damping_steps = 10000; UInt damping_interval = 100; Real damping_ratio = 0.5; Real imposed_velocity = 401.92; Real needed_time = 0.005; UInt additional_steps = 2000; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("sliding_cube_3d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); UInt max_steps = static_cast(needed_time*10/time_step) + imposing_steps + damping_steps + additional_steps; std::cout << "The number of time steps is found to be: " << max_steps << std::endl; Real * velocity_val = my_model.getVelocity().values; Real * acceleration_val = my_model.getAcceleration().values; my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); UniqueConstantFricCoef * fric_coef = new UniqueConstantFricCoef(*my_contact, master); fric_coef->setParam("mu", "0.3"); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // top boundary conditions -> imposing displacement for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.49) boundary[node*dim] = true; boundary[node*dim + 1] = true; boundary[node*dim + 2] = true; } UInt * top_nodes_val = top_nodes->values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coord_sliding_cube_3d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/sliding_cube_3d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream out_info; out_info.open("output_files/sliding_cube_3d.csv"); out_info << "%id,ftop,fcont,zone,stickNode,contNode" << std::endl; std::ofstream energy; energy.open("output_files/sliding_cube_3d_energy.csv"); energy << "%id,kin,pot,tot" << std::endl; Real * current_position = my_model.getCurrentPosition().values; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 20000 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } // impose normal displacement if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s > imposing_steps && s < imposing_steps+damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } // give initial velocity if(s == imposing_steps+damping_steps) { ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; bool * stick = imp_info->node_is_sticking->values; for(UInt i=0; i < imp_info->active_impactor_nodes->getSize(); ++i) { stick[i*2] = false; stick[i*2+1] = false; } UInt * connectivity = my_mesh.getConnectivity(element_type).values; UInt nb_nodes_elem = Mesh::getNbNodesPerElement(element_type); for(UInt i=0; i < nb_element; ++i) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,element_type,barycenter_p); if(barycenter_p[1] > -1) { for (UInt j=0; j < nb_nodes_elem; ++j) { velocity_val[connectivity[i*nb_nodes_elem+j]*dim] = imposed_velocity; acceleration_val[connectivity[i*nb_nodes_elem +j]*dim] = 0.; } } } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); my_contact->frictionPredictor(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } out_info << s << "," << top_force << "," << contact_force << "," << contact_zone << ","; // test if correct result is found if((s == max_steps) && (std::abs(contact_zone - 1.99367) > 1e-5)) { std::cout << "sliding distance = " << contact_zone << " but should be = 1.99367" << std::endl; return EXIT_FAILURE; } my_model.updateAcceleration(); const Vector * sticking_nodes = imp_info->node_is_sticking; bool * sticking_nodes_val = sticking_nodes->values; UInt nb_sticking_nodes = 0; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { if(sticking_nodes_val[i*2]) nb_sticking_nodes++; } out_info << nb_sticking_nodes << "," << imp_info->active_impactor_nodes->getSize() << std::endl; my_model.explicitCorr(); my_contact->frictionCorrector(); Real epot = my_model.getPotentialEnergy(); Real ekin = my_model.getKineticEnergy(); energy << s << "," << ekin << "," << epot << "," << ekin+epot << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } out_info.close(); energy.close(); delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/CMakeLists.txt index 5f2a36531..5a137e841 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/CMakeLists.txt @@ -1,41 +1,42 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Mon Mar 07 12:37:24 2011 # # @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 . # # @section DESCRIPTION # #=============================================================================== -add_mesh(test_ruina_slowness_mesh sliding_cube_2d.geo 2 1) -register_test(test_ruina_slowness_2d test_ruina_slowness_2d.cc) -add_dependencies(test_ruina_slowness_2d test_ruina_slowness_mesh) +#add_mesh(test_ruina_slowness_mesh sliding_cube_2d.geo 2 1) +# Memory leek to correct !!! +#register_test(test_ruina_slowness_2d test_ruina_slowness_2d.cc) +#add_dependencies(test_ruina_slowness_2d test_ruina_slowness_mesh) #=============================================================================== configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/material.dat ${CMAKE_CURRENT_BINARY_DIR}/material.dat COPYONLY ) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview/ruina_slowness_2d) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/test_ruina_slowness_2d.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/test_ruina_slowness_2d.cc index 62df1868f..b70c53cb6 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/test_ruina_slowness_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_friction_coefficient/test_ruina_slowness_2d.cc @@ -1,352 +1,352 @@ /** * @file test_ruina_slowness_2d.cc * @author David Kammer * @date Mon Mar 07 15:56:42 2011 * * @brief the slowness law of the simplified dieterich friction coefficient * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "friction_coefficient.hh" #include "simplified_dieterich_fric_coef.hh" #include "ruina_slowness_fric_coef.hh" #include "unique_constant_fric_coef.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #include "contact_search.hh" #include "contact_search_explicit.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); UInt dim = 2; const ElementType element_type = _triangle_3; #ifdef AKANTU_USE_IOHELPER const UInt paraview_type = TRIANGLE1; #endif //AKANTU_USE_IOHELPER //UInt max_steps = 200000; UInt imposing_steps = 1000; Real max_displacement = -0.01; UInt damping_steps = 100000; UInt damping_interval = 200; Real damping_ratio = 0.99; Real sliding_velocity = 10.; UInt nb_inc_vel_steps = 20000; Real updated_displacement = 0.; UInt additional_steps = 200000; UInt max_steps = imposing_steps + damping_steps + nb_inc_vel_steps + additional_steps; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("sliding_cube_2d.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); UInt nb_nodes = my_mesh.getNbNodes(); /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getBoundary().values, false, dim*nb_nodes*sizeof(bool)); my_model.initExplicit(); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); UInt nb_element = my_model.getFEM().getMesh().getNbElement(element_type); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); //UInt max_steps = static_cast(needed_time*10/time_step) + imposing_steps + damping_steps + additional_steps; std::cout << "The number of time steps is found to be: " << max_steps << std::endl; Real * velocity_val = my_model.getVelocity().values; my_model.assembleMassLumped(); Surface impactor = 0; Surface rigid_body_surface = 1; Surface master = 2; // modify surface id UInt nb_surfaces = my_mesh.getNbSurfaces(); my_mesh.setNbSurfaces(++nb_surfaces); ElementType surface_element_type = my_mesh.getFacetElementType(element_type); UInt nb_surface_element = my_model.getFEM().getMesh().getNbElement(surface_element_type); - UInt * surface_id_val = my_mesh.getSurfaceId(surface_element_type).values; + UInt * surface_id_val = my_mesh.getSurfaceID(surface_element_type).values; for(UInt i=0; i < nb_surface_element; ++i) { if (surface_id_val[i] == rigid_body_surface) { Real barycenter[dim]; Real * barycenter_p = &barycenter[0]; my_mesh.getBarycenter(i,surface_element_type,barycenter_p); if(barycenter_p[1] > -1.001) { surface_id_val[i] = master; } } } /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); /* UniqueConstantFricCoef * fric_coef = new UniqueConstantFricCoef(*my_contact, master); fric_coef->setParam("mu", "0.2"); */ RuinaSlownessFricCoef * fric_coef = new RuinaSlownessFricCoef(*my_contact, master); fric_coef->setParam("mu_zero", "0.2"); fric_coef->setParam("a_factor", "0.002"); fric_coef->setParam("b_factor", "0.08"); fric_coef->setParam("v_normalizer", "0.0001"); fric_coef->setParam("theta_normalizer", "0.002"); fric_coef->setParam("d_zero", "0.00001"); //my_contact->setFrictionCoefficient(fric_coef); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); my_contact->initSearch(); // does nothing so far // boundary conditions Vector * top_nodes = new Vector(0, 1); Vector * push_nodes = new Vector(0, 1); Real * coordinates = my_mesh.getNodes().values; Real * displacement = my_model.getDisplacement().values; bool * boundary = my_model.getBoundary().values; UInt * surface_to_nodes_offset = my_contact->getSurfaceToNodesOffset().values; UInt * surface_to_nodes = my_contact->getSurfaceToNodes().values; // normal force boundary conditions for(UInt n = surface_to_nodes_offset[impactor]; n < surface_to_nodes_offset[impactor+1]; ++n) { UInt node = surface_to_nodes[n]; Real x_coord = coordinates[node*dim]; Real y_coord = coordinates[node*dim + 1]; if (y_coord > -0.00001) { boundary[node*dim + 1] = true; top_nodes->push_back(node); } if (x_coord < 0.00001) { boundary[node*dim] = true; push_nodes->push_back(node); } } // ground boundary conditions for(UInt n = surface_to_nodes_offset[rigid_body_surface]; n < surface_to_nodes_offset[rigid_body_surface+1]; ++n) { UInt node = surface_to_nodes[n]; Real y_coord = coordinates[node*dim + 1]; if (y_coord < -1.49) boundary[node*dim] = true; boundary[node*dim + 1] = true; } UInt * top_nodes_val = top_nodes->values; UInt * push_nodes_val = push_nodes->values; my_model.updateResidual(); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_model.getFEM().getMesh().getNodes().values, dim, nb_nodes, "coord_ruina_slowness_2d"); dumper.SetConnectivity((int *)my_model.getFEM().getMesh().getConnectivity(element_type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(my_model.getDisplacement().values, dim, "displacements"); dumper.AddNodeDataField(my_model.getVelocity().values, dim, "velocity"); dumper.AddNodeDataField(my_model.getResidual().values, dim, "force"); dumper.AddNodeDataField(my_model.getForce().values, dim, "applied_force"); dumper.AddElemDataField(my_model.getMaterial(0).getStrain(element_type).values, dim*dim, "strain"); dumper.AddElemDataField(my_model.getMaterial(0).getStress(element_type).values, dim*dim, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/ruina_slowness_2d/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream out_info; out_info.open("ruina_slowness_2d.csv"); out_info << "%id,ftop,fcont,zone,stickNode,contNode" << std::endl; std::ofstream energy; energy.open("ruina_slowness_2d_energy.csv"); energy << "%id,kin,pot,tot" << std::endl; Real * current_position = my_model.getCurrentPosition().values; /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(UInt s = 1; s <= max_steps; ++s) { if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; if(s % 20000 == 0){ my_model.updateCurrentPosition(); my_contact->updateContact(); } // impose normal displacement if(s <= imposing_steps) { Real current_displacement = max_displacement/(static_cast(imposing_steps))*s; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; displacement[node*dim + 1] = current_displacement; } } // damp velocity in order to find equilibrium if(s > imposing_steps && s < imposing_steps+damping_steps && s%damping_interval == 0) { for (UInt i=0; i < nb_nodes; ++i) { for (UInt j=0; j < dim; ++j) velocity_val[i*dim + j] *= damping_ratio; } } // give initial velocity if(s > imposing_steps+damping_steps) { Real t_step = my_model.getTimeStep(); Real additional_disp; if (s > imposing_steps+damping_steps+nb_inc_vel_steps) additional_disp = sliding_velocity * t_step; else additional_disp = (s - (imposing_steps+damping_steps))/nb_inc_vel_steps*sliding_velocity*t_step; updated_displacement += additional_disp; for(UInt n=0; ngetSize(); ++n) { UInt node = push_nodes_val[n]; displacement[node*dim] = updated_displacement; } } my_model.explicitPred(); my_model.initializeUpdateResidualData(); my_contact->solveContact(); my_model.updateResidual(false); my_contact->avoidAdhesion(); my_contact->frictionPredictor(); // find the total force applied at the imposed displacement surface (top) Real * residual = my_model.getResidual().values; Real top_force = 0.; for(UInt n=0; ngetSize(); ++n) { UInt node = top_nodes_val[n]; top_force += residual[node*dim + 1]; } // find index of master surface in impactors_information ContactRigid::SurfaceToImpactInfoMap::const_iterator it_imp; it_imp = my_contact->getImpactorsInformation().find(master); // find the total contact force and contact area ContactRigid::ImpactorInformationPerMaster * imp_info = it_imp->second; UInt * active_imp_nodes_val = imp_info->active_impactor_nodes->values; Real contact_force = 0.; Real contact_zone = 0.; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { UInt node = active_imp_nodes_val[i]; contact_force += residual[node*dim + 1]; contact_zone = std::max(contact_zone, current_position[node*dim]); } out_info << s << "," << top_force << "," << contact_force << "," << contact_zone << ","; my_model.updateAcceleration(); const Vector * sticking_nodes = imp_info->node_is_sticking; bool * sticking_nodes_val = sticking_nodes->values; UInt nb_sticking_nodes = 0; for (UInt i = 0; i < imp_info->active_impactor_nodes->getSize(); ++i) { if(sticking_nodes_val[i*2]) nb_sticking_nodes++; } out_info << nb_sticking_nodes << "," << imp_info->active_impactor_nodes->getSize() << std::endl; my_model.explicitCorr(); my_contact->frictionCorrector(); Real epot = my_model.getPotentialEnergy(); Real ekin = my_model.getKineticEnergy(); energy << s << "," << ekin << "," << epot << "," << ekin+epot << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } out_info.close(); energy.close(); delete fric_coef; delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt index 7a0c8ed85..532f799e7 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/CMakeLists.txt @@ -1,31 +1,31 @@ #=============================================================================== # @file CMakeLists.txt # @author David Kammer # @date Mon Jan 17 11:30:13 2011 # # @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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== -add_subdirectory("test_regular_grid_neighbor_structure") -add_subdirectory("test_contact_2d_neighbor_structure") \ No newline at end of file +add_akantu_test(test_regular_grid_neighbor_structure "Regular grid neighbor structure tests") +add_akantu_test(test_contact_2d_neighbor_structure "Contact 2D neighbor structure tests") \ No newline at end of file diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt index cd0c83d56..61349b0e4 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/CMakeLists.txt @@ -1,32 +1,35 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi # @date Thu Dec 9 10:19:20 2010 # # @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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_contact_2d_neighbor_structure_mesh squares.geo 2 1) register_test(test_contact_2d_neighbor_structure test_contact_2d_neighbor_structure.cc) add_dependencies(test_contact_2d_neighbor_structure test_contact_2d_neighbor_structure_mesh) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) +file(COPY materials.dat DESTINATION .) diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc index b4e2baf4e..0a7761776 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_contact_2d_neighbor_structure/test_contact_2d_neighbor_structure.cc @@ -1,259 +1,259 @@ /** * @file test_contact_2d_neighbor_structure.cc * @author Leonardo Snozzi * @date Thu Dec 9 10:07:58 2010 * * @brief Test neighbor structure for 2d with linear triangles * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_2d_explicit.hh" #include "contact_neighbor_structure.hh" using namespace akantu; #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" static void initParaview(Mesh & mesh); static void initParaviewSurface(Mesh & mesh); static void printParaviewSurface(Mesh & mesh, const NeighborList & my_neighbor_list); double * facet_id; double * node_id; DumperParaview dumper_surface; #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); int spatial_dimension = 2; Real time_factor = 0.2; /// load mesh Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); UInt nb_elements = model->getFEM().getMesh().getNbElement(_triangle_3); /// model initialization + model->initModel(); model->initVectors(); model->readMaterials("materials.dat"); model->initMaterials(); model->initExplicit(); - model->initModel(); std::cout << model->getMaterial(0) << std::endl; model->assembleMassLumped(); /// set vectors to zero memset(model->getForce().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, spatial_dimension*nb_nodes*sizeof(Real)); memset(model->getMaterial(0).getStrain(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); memset(model->getMaterial(0).getStress(_triangle_3).values, 0, spatial_dimension*spatial_dimension*nb_elements*sizeof(Real)); /// Paraview Helper #ifdef AKANTU_USE_IOHELPER // initParaview(*model); #endif //AKANTU_USE_IOHELPER // /// dump surface information to paraview // #ifdef AKANTU_USE_IOHELPER // DumperParaview dumper; // dumper.SetMode(TEXT); // dumper.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "triangle_3_test-surface-extraction"); // dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, // TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); // dumper.SetPrefix("paraview/"); // dumper.Init(); // dumper.Dump(); // #endif //AKANTU_USE_IOHELPER Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); /// contact declaration Contact * contact = Contact::newContact(*model, _ct_2d_expli, _cst_2d_expli, _cnst_2d_grid); Contact2dExplicit * my_contact = dynamic_cast(contact); my_contact->initContact(true); my_contact->setFrictionCoefficient(0.); my_contact->initNeighborStructure(); /// get master surfaces with associated neighbor list const std::vector & master_surfaces = my_contact->getMasterSurfaces(); std::vector::iterator it; // for (it = master_surfaces.begin(); it != master_surfaces.end(); ++it) { #ifdef AKANTU_USE_IOHELPER initParaview(mesh); initParaviewSurface(mesh); #endif //AKANTU_USE_IOHELPER UInt nb_surfaces = mesh.getNbSurfaces(); for (UInt s = 0; s < nb_surfaces; ++s) { const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(s).getNeighborList(); #ifdef AKANTU_USE_IOHELPER printParaviewSurface(mesh, my_neighbor_list); #endif //AKANTU_USE_IOHELPER UInt nb_impactors = my_neighbor_list.impactor_nodes.getSize(); UInt * impactors_val = my_neighbor_list.impactor_nodes.values; - UInt * node_facet_off_val = my_neighbor_list.facets_offset[_segment_2]->values; - UInt * node_facet_val = my_neighbor_list.facets[_segment_2]->values; + UInt * node_facet_off_val = my_neighbor_list.facets_offset(_segment_2)->values; + UInt * node_facet_val = my_neighbor_list.facets(_segment_2)->values; /// print impactor nodes std::cout << "Master surface " << s << " has " << nb_impactors << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_impactors; ++i) { std::cout << " node " << impactors_val[i] << " : "; for (UInt j = node_facet_off_val[i]; j < node_facet_off_val[i+1]; ++j) std::cout << node_facet_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; } // } #ifdef AKANTU_USE_IOHELPER delete [] node_id; delete [] facet_id; #endif //AKANTU_USE_IOHELPER delete my_contact; delete model; finalize(); return EXIT_SUCCESS; } /// Paraview prints #ifdef AKANTU_USE_IOHELPER static void initParaview(Mesh & mesh) { DumperParaview dumper; dumper.SetMode(TEXT); UInt nb_nodes = mesh.getNbNodes(); dumper.SetPoints(mesh.getNodes().values, 2, nb_nodes, "test-2d-neighbor"); dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } static void initParaviewSurface(Mesh & mesh) { //DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); UInt nb_nodes = mesh.getNbNodes(); dumper_surface.SetPoints(mesh.getNodes().values, 2, nb_nodes, "test-2d-neighbor-surface"); dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_segment_2).values, LINE1, mesh.getNbElement(_segment_2), C_MODE); facet_id = new double [mesh.getConnectivity(_segment_2).getSize()]; memset(facet_id, 0, mesh.getConnectivity(_segment_2).getSize()*sizeof(double)); node_id = new double [nb_nodes]; memset(node_id, 0, nb_nodes*sizeof(double)); dumper_surface.AddElemDataField(facet_id, 1, "master_segments"); dumper_surface.AddNodeDataField(node_id, 1, "slave_nodes"); dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); // delete [] facet_id; // delete [] node_id; // return dumper_surface; } static void printParaviewSurface(Mesh & mesh, const NeighborList & my_neighbor_list) { UInt nb_impactors = my_neighbor_list.impactor_nodes.getSize(); UInt * impactors_val = my_neighbor_list.impactor_nodes.values; - UInt nb_facets = my_neighbor_list.facets[_segment_2]->getSize(); - UInt * node_facet_val = my_neighbor_list.facets[_segment_2]->values; + UInt nb_facets = my_neighbor_list.facets(_segment_2)->getSize(); + UInt * node_facet_val = my_neighbor_list.facets(_segment_2)->values; // double * node_id = new double [mesh.getNbNodes()]; memset(node_id, 0, mesh.getNbNodes()*sizeof(double)); // double * facet_id = new double [mesh.getConnectivity(_segment_2).getSize()]; memset(facet_id, 0, mesh.getConnectivity(_segment_2).getSize()*sizeof(double)); for (UInt n = 0; n < nb_impactors; ++n) node_id[impactors_val[n]] = 1.; for (UInt el = 0; el < nb_facets; ++el) facet_id[node_facet_val[el]] = 1.; dumper_surface.Dump(); } #endif //AKANTU_USE_IOHELPER diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc index 0a3df6fe4..f0e43f6ed 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_tetrahedron_4.cc @@ -1,168 +1,168 @@ /** * @file test_regular_grid_tetrahedron_4.cc * @author David Kammer * @date Tue Oct 26 16:58:42 2010 * * @brief test regular grid neighbor structure for 3d case * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #include "regular_grid_neighbor_structure.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); UInt dim = 3; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump facet information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_tetrahedron_4).values, TETRA1, my_mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); // initialize the vectors memset(my_model.getForce().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, 3*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, 3*nb_nodes*sizeof(Real)); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_2d_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); // how to use contact and contact search types for testing the reg grid with normal nl? my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList(); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; - UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset[_triangle_3]->values; - UInt * node_to_elem_val = my_neighbor_list.facets[_triangle_3]->values; + UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset(_triangle_3)->values; + UInt * node_to_elem_val = my_neighbor_list.facets(_triangle_3)->values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " node " << impact_nodes_val[i] << " : "; for (UInt j = node_to_elem_offset_val[i]; j < node_to_elem_offset_val[i+1]; ++j) std::cout << node_to_elem_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper_neighbor; dumper_neighbor.SetMode(TEXT); dumper_neighbor.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "tetrahedron_4_test-neighbor-elements"); dumper_neighbor.SetConnectivity((int *)my_mesh.getConnectivity(_triangle_3).values, TRIANGLE1, my_mesh.getNbElement(_triangle_3), C_MODE); double * neigh_elem = new double [my_mesh.getNbElement(_triangle_3)]; for (UInt i = 0; i < my_mesh.getNbElement(_triangle_3); ++i) neigh_elem[i] = 0.0; UInt visualize_node = 7; UInt n = impact_nodes_val[visualize_node]; std::cout << "plot for node: " << n << std::endl; for (UInt i = node_to_elem_offset_val[visualize_node]; i < node_to_elem_offset_val[visualize_node+1]; ++i) neigh_elem[node_to_elem_val[i]] = 1.; dumper_neighbor.AddElemDataField(neigh_elem, 1, "neighbor id"); dumper_neighbor.SetPrefix("paraview/"); dumper_neighbor.Init(); dumper_neighbor.Dump(); delete [] neigh_elem; #endif //AKANTU_USE_IOHELPER delete my_contact; finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc index fed09ea99..f5de1f571 100644 --- a/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc +++ b/test/test_model/test_solid_mechanics_model/test_contact/test_neighbor_structure/test_regular_grid_neighbor_structure/test_regular_grid_triangle_3.cc @@ -1,164 +1,164 @@ /** * @file test_regular_grid_triangle_3.cc * @author David Kammer * @date Tue Oct 26 16:58:42 2010 * * @brief test regular grid neighbor structure for 3d case * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "contact.hh" #include "contact_rigid.hh" #include "contact_neighbor_structure.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); int dim = 2; /// load mesh Mesh my_mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", my_mesh); /// build facet connectivity and surface id MeshUtils::buildFacets(my_mesh,1,0); MeshUtils::buildSurfaceID(my_mesh); unsigned int nb_nodes = my_mesh.getNbNodes(); /// dump surface information to paraview #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_test-surface-extraction"); dumper.SetConnectivity((int*)my_mesh.getConnectivity(_triangle_3).values, TRIANGLE1, my_mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER /// declaration of model SolidMechanicsModel my_model(my_mesh); /// model initialization my_model.initVectors(); /// initialize the vectors memset(my_model.getForce().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getVelocity().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getAcceleration().values, 0, dim*nb_nodes*sizeof(Real)); memset(my_model.getDisplacement().values, 0, dim*nb_nodes*sizeof(Real)); my_model.initModel(); my_model.readMaterials("material.dat"); my_model.initMaterials(); Real time_step = my_model.getStableTimeStep(); my_model.setTimeStep(time_step/10.); my_model.assembleMassLumped(); /// contact declaration Contact * contact = Contact::newContact(my_model, _ct_rigid, _cst_2d_expli, _cnst_regular_grid); ContactRigid * my_contact = dynamic_cast(contact); my_contact->initContact(false); Surface master = 0; Surface impactor = 1; my_contact->addMasterSurface(master); my_contact->addImpactorSurfaceToMasterSurface(impactor, master); my_model.updateCurrentPosition(); // neighbor structure uses current position for init my_contact->initNeighborStructure(master); const NeighborList & my_neighbor_list = my_contact->getContactSearch().getContactNeighborStructure(master).getNeighborList(); UInt nb_nodes_neigh = my_neighbor_list.impactor_nodes.getSize(); Vector impact_nodes = my_neighbor_list.impactor_nodes; UInt * impact_nodes_val = impact_nodes.values; - UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset[_segment_2]->values; - UInt * node_to_elem_val = my_neighbor_list.facets[_segment_2]->values; + UInt * node_to_elem_offset_val = my_neighbor_list.facets_offset(_segment_2)->values; + UInt * node_to_elem_val = my_neighbor_list.facets(_segment_2)->values; /// print impactor nodes std::cout << "we have " << nb_nodes_neigh << " impactor nodes:" << std::endl; for (UInt i = 0; i < nb_nodes_neigh; ++i) { std::cout << " node " << impact_nodes_val[i] << " : "; for (UInt j = node_to_elem_offset_val[i]; j < node_to_elem_offset_val[i+1]; ++j) std::cout << node_to_elem_val[j] << " "; std::cout << std::endl; } std::cout << std::endl; #ifdef AKANTU_USE_IOHELPER DumperParaview dumper_neighbor; dumper_neighbor.SetMode(TEXT); dumper_neighbor.SetPoints(my_mesh.getNodes().values, dim, nb_nodes, "triangle_3_test-neighbor-elements"); dumper_neighbor.SetConnectivity((int *)my_mesh.getConnectivity(_segment_2).values, LINE1, my_mesh.getNbElement(_segment_2), C_MODE); double * neigh_elem = new double [my_mesh.getNbElement(_segment_2)]; for (UInt i = 0; i < my_mesh.getNbElement(_segment_2); ++i) neigh_elem[i] = 0.0; UInt visualize_node = 1; UInt n = impact_nodes_val[visualize_node]; std::cout << "plot for node: " << n << std::endl; for (UInt i = node_to_elem_offset_val[visualize_node]; i < node_to_elem_offset_val[visualize_node+1]; ++i) neigh_elem[node_to_elem_val[i]] = 1.; dumper_neighbor.AddElemDataField(neigh_elem, 1, "neighbor id"); dumper_neighbor.SetPrefix("paraview/"); dumper_neighbor.Init(); dumper_neighbor.Dump(); delete [] neigh_elem; #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc index 07381c8f1..7ee6884af 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.cc @@ -1,159 +1,156 @@ /** * @file local_material_damage.cc * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 11:53:52 2010 * * @brief Specialization of the material class for the damage material * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "local_material_damage.hh" #include "solid_mechanics_model.hh" __BEGIN_AKANTU__ /* -------------------------------------------------------------------------- */ LocalMaterialDamage::LocalMaterialDamage(Model & model, const MaterialID & id) : Material(model, id) { AKANTU_DEBUG_IN(); rho = 0; E = 0; nu = 1./2.; Yd = 50; Sd = 5000; - for(UInt t = _not_defined; t < _max_element_type; ++t) - this->damage[t] = NULL; - AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::initMaterial() { AKANTU_DEBUG_IN(); Material::initMaterial(); const Mesh::ConnectivityTypeList & type_list = model->getFEM().getMesh().getConnectivityTypeList(); Mesh::ConnectivityTypeList::const_iterator it; for(it = type_list.begin(); it != type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; std::stringstream sstr_damage; sstr_damage << id << ":damage:" << *it; - damage[*it] = &(alloc(sstr_damage.str(), 0, + damage(*it) = &(alloc(sstr_damage.str(), 0, 1, REAL_INIT_VALUE)); } lambda = nu * E / ((1 + nu) * (1 - 2*nu)); mu = E / (2 * (1 + nu)); kpa = lambda + 2./3. * mu; is_init = true; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::computeStress(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); Real F[3*3]; Real sigma[3*3]; - damage[el_type]->resize(model->getFEM().getNbQuadraturePoints(el_type)*element_filter[el_type]->getSize()); - Real * dam = damage[el_type]->values; + damage(el_type, ghost_type)->resize(model->getFEM().getNbQuadraturePoints(el_type, ghost_type)*element_filter(el_type, ghost_type)->getSize()); + Real * dam = damage(el_type, ghost_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; memset(F, 0, 3 * 3 * sizeof(Real)); for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) F[3*i + j] = strain_val[spatial_dimension * i + j]; for (UInt i = 0; i < spatial_dimension; ++i) F[i*3 + i] -= 1; computeStress(F, sigma,*dam); ++dam; for (UInt i = 0; i < spatial_dimension; ++i) for (UInt j = 0; j < spatial_dimension; ++j) stress_val[spatial_dimension*i + j] = sigma[3 * i + j]; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::computePotentialEnergy(ElementType el_type, GhostType ghost_type) { AKANTU_DEBUG_IN(); if(ghost_type != _not_ghost) return; - Real * epot = potential_energy[el_type]->values; + Real * epot = potential_energy(el_type)->values; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_BEGIN; computePotentialEnergy(strain_val, stress_val, epot); epot++; MATERIAL_STRESS_QUADRATURE_POINT_LOOP_END; AKANTU_DEBUG_OUT(); } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::setParam(const std::string & key, const std::string & value, const MaterialID & id) { std::stringstream sstr(value); if(key == "rho") { sstr >> rho; } else if(key == "E") { sstr >> E; } else if(key == "nu") { sstr >> nu; } else if(key == "Yd") { sstr >> Yd; } else if(key == "Sd") { sstr >> Sd; } else { Material::setParam(key, value, id); } } /* -------------------------------------------------------------------------- */ void LocalMaterialDamage::printself(std::ostream & stream, int indent) const { std::string space; for(Int i = 0; i < indent; i++, space += AKANTU_INDENT); stream << space << "Material<_damage> [" << std::endl; stream << space << " + id : " << id << std::endl; stream << space << " + name : " << name << std::endl; stream << space << " + density : " << rho << std::endl; stream << space << " + Young's modulus : " << E << std::endl; stream << space << " + Poisson's ratio : " << nu << std::endl; stream << space << " + Yd : " << Yd << std::endl; stream << space << " + Sd : " << Sd << std::endl; if(is_init) { stream << space << " + First Lamé coefficient : " << lambda << std::endl; stream << space << " + Second Lamé coefficient : " << mu << std::endl; stream << space << " + Bulk coefficient : " << kpa << std::endl; } stream << space << "]" << std::endl; } /* -------------------------------------------------------------------------- */ __END_AKANTU__ diff --git a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh index 0ed35f041..198c6e915 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh +++ b/test/test_model/test_solid_mechanics_model/test_materials/local_material_damage.hh @@ -1,139 +1,139 @@ /** * @file local_material_damage.hh * @author Nicolas Richart * @author Guillaume Anciaux * @author Marion Chambart * @date Thu Jul 29 15:00:59 2010 * * @brief Material isotropic elastic * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifndef __AKANTU_LOCAL_MATERIAL_DAMAGE_HH__ #define __AKANTU_LOCAL_MATERIAL_DAMAGE_HH__ __BEGIN_AKANTU__ class LocalMaterialDamage : public Material { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: LocalMaterialDamage(Model & model, const MaterialID & id = ""); virtual ~LocalMaterialDamage() {}; /* ------------------------------------------------------------------------ */ /* Methods */ /* ------------------------------------------------------------------------ */ public: void initMaterial(); void setParam(const std::string & key, const std::string & value, const MaterialID & id); /// constitutive law for all element of a type void computeStress(ElementType el_type, GhostType ghost_type = _not_ghost); /// constitutive law for a given quadrature point inline void computeStress(Real * F, Real * sigma,Real & damage); /// compute tangent stiffness virtual void computeTangentStiffness(__attribute__ ((unused)) const ElementType & el_type, __attribute__ ((unused)) Vector & tangent_matrix, __attribute__ ((unused)) GhostType ghost_type = _not_ghost) {}; /// compute the potential energy for all elements void computePotentialEnergy(ElementType el_type, GhostType ghost_type = _not_ghost); /// compute the potential energy for on element inline void computePotentialEnergy(Real * F, Real * sigma, Real * epot); /// compute the celerity of wave in the material inline Real celerity(); /// function to print the containt of the class virtual void printself(std::ostream & stream, int indent = 0) const; /* ------------------------------------------------------------------------ */ /* Accessors */ /* ------------------------------------------------------------------------ */ public: /// get the stable time step inline Real getStableTimeStep(Real h, const Element & element); /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(Damage, damage, const Vector &); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(Damage, damage, Real); private: /// the young modulus Real E; /// Poisson coefficient Real nu; /// First Lamé coefficient Real lambda; /// Second Lamé coefficient (shear modulus) Real mu; /// resistance to damage Real Yd; /// damage threshold Real Sd; /// Bulk modulus Real kpa; /// damage internal variable ByElementTypeReal damage; }; /* -------------------------------------------------------------------------- */ /* inline functions */ /* -------------------------------------------------------------------------- */ #include "local_material_damage_inline_impl.cc" /* -------------------------------------------------------------------------- */ /// standard output stream operator inline std::ostream & operator <<(std::ostream & stream, const LocalMaterialDamage & _this) { _this.printself(stream); return stream; } __END_AKANTU__ #endif /* __AKANTU_LOCAL_MATERIAL_DAMAGE_HH__ */ diff --git a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc index 32a412d63..8f11f8c3d 100644 --- a/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc +++ b/test/test_model/test_solid_mechanics_model/test_materials/test_local_material.cc @@ -1,161 +1,161 @@ /** * @file test_local_material.cc * @author Guillaume Anciaux * @author Marion Chambart * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "fem.hh" #include "local_material_damage.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; akantu::Real eps = 1e-10; static void trac(__attribute__ ((unused)) double * position,double * stress){ memset(stress, 0, sizeof(Real)*4); if (fabs(position[0] - 10) < eps){ stress[0] = 3e6; stress[3] = 3e6; } } int main(int argc, char *argv[]) { akantu::initialize(&argc,&argv); - UInt max_steps = 20000; + UInt max_steps = 2000; Real epot, ekin; Real bar_height = 4.; const UInt spatial_dimension = 2; Mesh mesh(spatial_dimension); MeshIOMSH mesh_io; // mesh_io.read("bar.msh", mesh); mesh_io.read("barre_trou.msh", mesh); SolidMechanicsModel * model = new SolidMechanicsModel(mesh); /// model initialization model->initVectors(); UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); memset(model->getForce().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getVelocity().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getAcceleration().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getDisplacement().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getResidual().values, 0, 2*nb_nodes*sizeof(Real)); memset(model->getMass().values, 1, nb_nodes*sizeof(Real)); model->initExplicit(); model->initModel(); model->readCustomMaterial("material.dat","LOCAL_DAMAGE"); model->initMaterials(); Real time_step = model->getStableTimeStep(); model->setTimeStep(time_step/10.); model->assembleMassLumped(); std::cout << *model << std::endl; /// Dirichlet boundary conditions for (akantu::UInt i = 0; i < nb_nodes; ++i) { if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) model->getBoundary().values[spatial_dimension*i] = true; if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= bar_height - eps ) { model->getBoundary().values[spatial_dimension*i + 1] = true; } } FEM & fem_boundary = model->getFEMBoundary(); fem_boundary.initShapeFunctions(); fem_boundary.computeNormalsOnControlPoints(); model->computeForcesFromFunction(trac, akantu::_bft_stress); #ifdef AKANTU_USE_IOHELPER model->updateResidual(); DumperParaview dumper; dumper.SetMode(BASE64); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, 2, nb_nodes, "coordinates"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(_triangle_6).values, TRIANGLE2, model->getFEM().getMesh().getNbElement(_triangle_6), C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, 2, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, 2, "velocity"); dumper.AddNodeDataField(model->getForce().values, 2, "force"); dumper.AddNodeDataField(model->getMass().values, 1, "Mass"); dumper.AddNodeDataField(model->getResidual().values, 2, "residual"); dumper.AddElemDataField(model->getMaterial(0).getStrain(_triangle_6).values, 4, "strain"); dumper.AddElemDataField(model->getMaterial(0).getStress(_triangle_6).values, 4, "stress"); LocalMaterialDamage * mat = dynamic_cast(&(model->getMaterial(0))); AKANTU_DEBUG_ASSERT(mat,"material is not having the right type: something is wrong"); Real * dam = mat->getDamage(_triangle_6).values; dumper.AddElemDataField(dam, 1, "damage"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("force", 1); dumper.SetEmbeddedValue("residual", 1); dumper.SetEmbeddedValue("velocity", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER for(UInt s = 0; s < max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); epot = model->getPotentialEnergy(); ekin = model->getKineticEnergy(); - std::cout << s << " " << epot << " " << ekin << " " << epot + ekin - << std::endl; + if(s % 100 == 0) std::cout << s << " " << epot << " " << ekin << " " << epot + ekin + << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) dumper.Dump(); #endif //AKANTU_USE_IOHELPER } akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc index ba91b0cef..b3191fcd7 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d.cc @@ -1,327 +1,294 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER //#define CHECK_STRESS akantu::ElementType type = akantu::_triangle_6; #ifdef AKANTU_USE_IOHELPER akantu::UInt paraview_type = TRIANGLE2; #endif //AKANTU_USE_IOHELPER akantu::SolidMechanicsModel * model; akantu::UInt spatial_dimension = 2; akantu::UInt nb_nodes; akantu::UInt nb_element; akantu::UInt nb_quadrature_points; akantu::Vector * stress; akantu::Vector * strain; akantu::Vector * damage; #ifdef AKANTU_USE_IOHELPER void paraviewInit(Dumper & dumper); void paraviewDump(Dumper & dumper); #endif int main(int argc, char *argv[]) { akantu::initialize(&argc,&argv); - akantu::UInt max_steps = 1000; - akantu::Real time_factor = 0.2; + akantu::UInt max_steps = 5000; + akantu::Real time_factor = 0.8; // akantu::Real epot, ekin; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("bar2.msh", mesh); model = new akantu::SolidMechanicsModel(mesh); nb_nodes = model->getFEM().getMesh().getNbNodes(); nb_element = model->getFEM().getMesh().getNbElement(type); - /// model initialization model->initVectors(); /// set vectors to 0 - memset(model->getForce().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model->getVelocity().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model->getAcceleration().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model->getDisplacement().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); + model->getForce().clear(); + model->getVelocity().clear(); + model->getAcceleration().clear(); + model->getDisplacement().clear(); model->initExplicit(); model->initModel(); model->readMaterials("material.dat"); std::cout << model->getMaterial(0) << std::endl; - std::cout << model->getMaterial(1) << std::endl; - - // akantu::Vector & elem_mat = model->getElementMaterial(type); - // for (akantu::UInt e = 0; e < nb_element; ++e) { - // akantu::Real barycenter[spatial_dimension]; - // mesh.getBarycenter(e, type, barycenter, akantu::_not_ghost); - // if(barycenter[1] <= 0.75 && barycenter[1] >= 0.25) - // elem_mat(e, 0) = 0; - // else elem_mat(e, 0) = 1; - // } model->initMaterials(); model->assembleMassLumped(); nb_quadrature_points = model->getFEM().getNbQuadraturePoints(type); stress = new akantu::Vector(nb_element * nb_quadrature_points, spatial_dimension* spatial_dimension); strain = new akantu::Vector(nb_element * nb_quadrature_points, spatial_dimension * spatial_dimension); - damage = new akantu::Vector(nb_element * nb_quadrature_points, 1); - memset(damage->values, 0, nb_quadrature_points * nb_element * sizeof(akantu::Real)); - -#ifdef AKANTU_USE_IOHELPER - /// set to 0 only for the first paraview dump - memset(model->getResidual().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - // memset(model->getMaterial(0).getStrain(type).values, 0, - // spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); - // memset(model->getMaterial(0).getStress(type).values, 0, - // spatial_dimension*spatial_dimension*nb_element*sizeof(akantu::Real)); -#endif //AKANTU_USE_IOHELPER - /// boundary conditions akantu::Real eps = 1e-16; - for (akantu::UInt i = 0; i < nb_nodes; ++i) { - if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] >= 9) - model->getDisplacement().values[spatial_dimension*i] = (model->getFEM().getMesh().getNodes().values[spatial_dimension*i] - 9) / 10000. ; - - if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i] <= eps) - model->getBoundary().values[spatial_dimension*i] = true; + const akantu::Vector & pos = mesh.getNodes(); + akantu::Vector & disp = model->getDisplacement(); + akantu::Vector & boun = model->getBoundary(); - if(model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] <= eps || - model->getFEM().getMesh().getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { - model->getBoundary().values[spatial_dimension*i + 1] = true; - } + for (akantu::UInt i = 0; i < nb_nodes; ++i) { + if(pos(i, 0) >= 9.) disp(i, 0) = (pos(i, 0) - 9) / 100.; + if(pos(i) <= eps) boun(i, 0) = true; + if(pos(i, 1) <= eps || pos(i, 1) >= 1 - eps ) boun(i, 1) = true; } /// set the time step akantu::Real time_step = model->getStableTimeStep() * time_factor; std::cout << "Time Step = " << time_step << "s" << std::endl; model->setTimeStep(time_step); #ifdef AKANTU_USE_IOHELPER /// initialize the paraview output + model->updateResidual(); DumperParaview dumper; paraviewInit(dumper); #endif //AKANTU_USE_IOHELPER #ifdef CHECK_STRESS std::ofstream outfile; outfile.open("stress"); #endif // CHECK_STRESS std::ofstream energy; - energy.open("energy.csv"); - energy << "id,epot,ekin,tot" << std::endl; + energy.open("energy_bar_2d.csv"); + energy << "id,rtime,epot,ekin,tot" << std::endl; for(akantu::UInt s = 1; s <= max_steps; ++s) { model->explicitPred(); model->updateResidual(); model->updateAcceleration(); model->explicitCorr(); akantu::Real epot = model->getPotentialEnergy(); akantu::Real ekin = model->getKineticEnergy(); - std::cerr << "passing step " << s << "/" << max_steps << std::endl; - energy << s << "," << epot << "," << ekin << "," << epot + ekin + energy << s << "," << (s-1)*time_step << "," << epot << "," << ekin << "," << epot + ekin << std::endl; #ifdef CHECK_STRESS /// search the position of the maximum of stress to determine the wave speed akantu::Real max_stress = std::numeric_limits::min(); akantu::Real * stress = model->getMaterial(0).getStress(type).values; for (akantu::UInt i = 0; i < nb_element; ++i) { if(max_stress < stress[i*spatial_dimension*spatial_dimension]) { max_stress = stress[i*spatial_dimension*spatial_dimension]; } } akantu::Real * coord = model->getFEM().getMesh().getNodes().values; akantu::Real * disp_val = model->getDisplacement().values; akantu::UInt * conn = model->getFEM().getMesh().getConnectivity(type).values; akantu::UInt nb_nodes_per_element = model->getFEM().getMesh().getNbNodesPerElement(type); akantu::Real * coords = new akantu::Real[spatial_dimension]; akantu::Real min_x = std::numeric_limits::max(); akantu::Real max_x = std::numeric_limits::min(); akantu::Real stress_range = 5e7; for (akantu::UInt el = 0; el < nb_element; ++el) { if(stress[el*spatial_dimension*spatial_dimension] > max_stress - stress_range) { akantu::UInt el_offset = el * nb_nodes_per_element; memset(coords, 0, spatial_dimension*sizeof(akantu::Real)); for (akantu::UInt n = 0; n < nb_nodes_per_element; ++n) { for (akantu::UInt i = 0; i < spatial_dimension; ++i) { akantu::UInt node = conn[el_offset + n] * spatial_dimension; coords[i] += (coord[node + i] + disp_val[node + i]) / ((akantu::Real) nb_nodes_per_element); } } min_x = min_x < coords[0] ? min_x : coords[0]; max_x = max_x > coords[0] ? max_x : coords[0]; } } outfile << s << " " << .5 * (min_x + max_x) << " " << min_x << " " << max_x << " " << max_x - min_x << " " << max_stress << std::endl; delete [] coords; #endif // CHECK_STRESS #ifdef AKANTU_USE_IOHELPER if(s % 100 == 0) paraviewDump(dumper); #endif //AKANTU_USE_IOHELPER - if(s % 10 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; + if(s % 100 == 0) std::cout << "passing step " << s << "/" << max_steps << std::endl; } energy.close(); #ifdef CHECK_STRESS outfile.close(); #endif // CHECK_STRESS delete model; akantu::finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ /* Dumper vars */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER void paraviewInit(Dumper & dumper) { dumper.SetMode(TEXT); dumper.SetPoints(model->getFEM().getMesh().getNodes().values, - spatial_dimension, nb_nodes, "coordinates"); + spatial_dimension, nb_nodes, "bar2d"); dumper.SetConnectivity((int *)model->getFEM().getMesh().getConnectivity(type).values, paraview_type, nb_element, C_MODE); dumper.AddNodeDataField(model->getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model->getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model->getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddNodeDataField(model->getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model->getMass().values, 1, "mass"); dumper.AddNodeDataField(model->getForce().values, spatial_dimension, "applied_force"); akantu::Real * mat = new akantu::Real[nb_element * nb_quadrature_points]; akantu::Vector & elem_mat = model->getElementMaterial(type); for (akantu::UInt e = 0; e < nb_element; ++e) { for (akantu::UInt q = 0; q < nb_quadrature_points; ++q) { - mat[e * nb_quadrature_points + q] = elem_mat(e, 0); + mat[e * nb_quadrature_points + q] = elem_mat(e, 0); } } akantu::UInt offset = nb_quadrature_points * spatial_dimension * spatial_dimension; akantu::UInt nb_mat = model->getNbMaterials(); for (akantu::UInt m = 0; m < nb_mat; ++m) { akantu::Material & material = model->getMaterial(m); const akantu::Vector & elmat = material.getElementFilter(type); for (akantu::UInt e = 0; e < elmat.getSize(); ++e) { memcpy(stress->values + elmat(e, 0) * offset, material.getStress(type).values + e * offset, offset * sizeof(akantu::Real)); memcpy(strain->values + elmat(e, 0) * offset, material.getStrain(type).values + e * offset, offset * sizeof(akantu::Real)); } } dumper.AddElemDataField(mat, 1, "material"); dumper.AddElemDataField(strain->values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(stress->values, spatial_dimension*spatial_dimension, "stress"); - dumper.AddElemDataField(damage->values, - 1, "damage"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { akantu::UInt offset = nb_quadrature_points * spatial_dimension * spatial_dimension; akantu::UInt nb_mat = model->getNbMaterials(); for (akantu::UInt m = 0; m < nb_mat; ++m) { akantu::Material & material = model->getMaterial(m); const akantu::Vector & elmat = material.getElementFilter(type); for (akantu::UInt e = 0; e < elmat.getSize(); ++e) { memcpy(stress->values + elmat(e, 0) * offset, material.getStress(type).values + e * offset, offset * sizeof(akantu::Real)); memcpy(strain->values + elmat(e, 0) * offset, material.getStrain(type).values + e * offset, offset * sizeof(akantu::Real)); } } dumper.Dump(); } #endif diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc index 722ceedfe..d8012809e 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_bar_traction2d_parallel.cc @@ -1,229 +1,215 @@ /** * @file test_solid_mechanics_model.cc * @author Nicolas Richart * @date Tue Jul 27 14:34:13 2010 * * @brief test of the class SolidMechanicsModel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "distributed_synchronizer.hh" #include "mesh_partition_scotch.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER int main(int argc, char *argv[]) { #ifdef AKANTU_USE_IOHELPER akantu::ElementType type = akantu::_triangle_6; #endif //AKANTU_USE_IOHELPER akantu::UInt spatial_dimension = 2; akantu::UInt max_steps = 5000; akantu::Real time_factor = 0.8; akantu::initialize(&argc, &argv); akantu::Mesh mesh(spatial_dimension); akantu::StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); akantu::Int psize = comm->getNbProc(); akantu::Int prank = comm->whoAmI(); // std::stringstream filename; // filename << "log-" << prank << ".txt"; // akantu::debug::setLogFile(filename.str()); akantu::debug::setDebugLevel(akantu::dblWarning); akantu::MeshPartition * partition = NULL; if(prank == 0) { akantu::MeshIOMSH mesh_io; mesh_io.read("bar2.msh", mesh); partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); } akantu::SolidMechanicsModel model(mesh); model.initParallel(partition); akantu::UInt nb_nodes = mesh.getNbNodes(); #ifdef AKANTU_USE_IOHELPER akantu::UInt nb_element = mesh.getNbElement(type); #endif //AKANTU_USE_IOHELPER /* ------------------------------------------------------------------------ */ /* Initialization */ /* ------------------------------------------------------------------------ */ /// model initialization model.initVectors(); /// set vectors to 0 - memset(model.getForce().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model.getResidual().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model.getVelocity().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model.getAcceleration().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - memset(model.getDisplacement().values, 0, - spatial_dimension*nb_nodes*sizeof(akantu::Real)); - + model.getForce().clear(); + model.getVelocity().clear(); + model.getAcceleration().clear(); + model.getDisplacement().clear(); model.initExplicit(); model.initModel(); model.readMaterials("material.dat"); model.initMaterials(); if(prank == 0) std::cout << model.getMaterial(0) << std::endl; model.assembleMassLumped(); /* ------------------------------------------------------------------------ */ /* Boundary + initial conditions */ /* ------------------------------------------------------------------------ */ akantu::Real eps = 1e-16; + const akantu::Vector & pos = mesh.getNodes(); + akantu::Vector & disp = model.getDisplacement(); + akantu::Vector & boun = model.getBoundary(); + for (akantu::UInt i = 0; i < nb_nodes; ++i) { - // model.getDisplacement().values[spatial_dimension*i] - // = mesh.getNodes().values[spatial_dimension*i] / 100.; - if(mesh.getNodes().values[spatial_dimension*i] >= 9) - model.getDisplacement().values[spatial_dimension*i] - = (mesh.getNodes().values[spatial_dimension*i] - 9) / 100.; - - if(mesh.getNodes().values[spatial_dimension*i] <= eps) - model.getBoundary().values[spatial_dimension*i] = true; - - if(mesh.getNodes().values[spatial_dimension*i + 1] <= eps || - mesh.getNodes().values[spatial_dimension*i + 1] >= 1 - eps ) { - model.getBoundary().values[spatial_dimension*i + 1] = true; - } + if(pos(i, 0) >= 9.) disp(i, 0) = (pos(i, 0) - 9) / 100.; + if(pos(i) <= eps) boun(i, 0) = true; + if(pos(i, 1) <= eps || pos(i, 1) >= 1 - eps ) boun(i, 1) = true; } model.synchronizeBoundaries(); - #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(mesh.getNodes().values, spatial_dimension, nb_nodes, "bar2d_para"); dumper.SetConnectivity((int *)mesh.getConnectivity(type).values, TRIANGLE2, nb_element, C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getMass().values, 1, "mass"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "force"); dumper.AddNodeDataField(model.getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddElemDataField(model.getMaterial(0).getStrain(type).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStress(type).values, spatial_dimension*spatial_dimension, "stress"); akantu::UInt nb_quadrature_points = model.getFEM().getNbQuadraturePoints(type); double * part = new double[nb_element*nb_quadrature_points]; for (unsigned int i = 0; i < nb_element; ++i) for (unsigned int q = 0; q < nb_quadrature_points; ++q) part[i*nb_quadrature_points + q] = prank; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); #endif //AKANTU_USE_IOHELPER std::ofstream energy; if(prank == 0) { - energy.open("energy.csv"); - energy << "id,epot,ekin,tot" << std::endl; + energy.open("energy_bar_2d_para.csv"); + energy << "id,rtime,epot,ekin,tot" << std::endl; } double total_time = 0.; /// Setting time step akantu::Real time_step = model.getStableTimeStep() * time_factor; if(prank == 0) std::cout << "Time Step = " << time_step << "s" << std::endl; model.setTimeStep(time_step); /* ------------------------------------------------------------------------ */ /* Main loop */ /* ------------------------------------------------------------------------ */ for(akantu::UInt s = 1; s <= max_steps; ++s) { double start = MPI_Wtime(); model.explicitPred(); model.updateResidual(); model.updateAcceleration(); model.explicitCorr(); double end = MPI_Wtime(); akantu::Real epot = model.getPotentialEnergy(); akantu::Real ekin = model.getKineticEnergy(); total_time += end - start; - if(prank == 0 && (s % 10 == 0)) { - std::cerr << "passing step " << s << "/" << max_steps << std::endl; - energy << s << "," << epot << "," << ekin << "," << epot + ekin - << std::endl; + if(prank == 0 && (s % 100 == 0)) { + std::cerr << "passing step " << s << "/" << max_steps << std::endl; } + energy << s << "," << (s-1)*time_step << "," << epot << "," << ekin << "," << epot + ekin + << std::endl; #ifdef AKANTU_USE_IOHELPER - if(s % 10 == 0) { + if(s % 100 == 0) { dumper.Dump(); } #endif //AKANTU_USE_IOHELPER } if(prank == 0) std::cout << "Time : " << psize << " " << total_time / max_steps << " " << total_time << std::endl; #ifdef AKANTU_USE_IOHELPER delete [] part; #endif //AKANTU_USE_IOHELPER akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc index 0c90b8eb2..08709a46e 100644 --- a/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc +++ b/test/test_model/test_solid_mechanics_model/test_solid_mechanics_model_implicit_dynamic_2d.cc @@ -1,312 +1,312 @@ /** * @file test_solid_mechanics_model_implicit_dynamic_2d.cc * @author Nicolas Richart * @date Fri Apr 29 11:32:25 2011 * * @brief test of the dynamic implicit code * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "solid_mechanics_model.hh" #include "material.hh" #include "static_communicator.hh" #include "distributed_synchronizer.hh" #include "mesh_partition_scotch.hh" #ifdef AKANTU_USE_SCOTCH #include "mesh_partition_scotch.hh" #endif using namespace akantu; /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" void paraviewInit(Dumper & dumper, const SolidMechanicsModel & model); void paraviewDump(Dumper & dumper); #endif /* -------------------------------------------------------------------------- */ const Real F = 0.5e4; #define bar_length 10. #define bar_height 1. #define bar_depth 1. -const ElementType TYPE = _tetrahedron_10; +const ElementType TYPE = _triangle_3; -UInt spatial_dimension = 3; +UInt spatial_dimension = 2; Real time_step = 1e-4; Real analytical_solution(Real time) { return 1./pow(M_PI, 4) * ((1. - cos(M_PI*M_PI*time)) + (1. - cos(3*3*M_PI*M_PI*time))/81. + (1. - cos(5*5*M_PI*M_PI*time))/625.); } /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { debug::setDebugLevel(dblWarning); initialize(&argc, &argv); Mesh mesh(spatial_dimension); StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm->getNbProc(); Int prank = comm->whoAmI(); MeshPartition * partition = NULL; if(prank == 0) { MeshIOMSH mesh_io; - mesh_io.read("beam_3d_quad.msh", mesh); + mesh_io.read("beam_2d_lin.msh", mesh); partition = new MeshPartitionScotch(mesh, spatial_dimension); partition->reorder(); partition->partitionate(psize); } SolidMechanicsModel * model = new SolidMechanicsModel(mesh); model->initParallel(partition); // UInt nb_nodes = model->getFEM().getMesh().getNbNodes(); /// model initialization model->initVectors(); model->initModel(); model->readMaterials("material_implicit_dynamic.dat"); model->initMaterials(); model->initImplicit(true); // boundary conditions const Vector & position = mesh.getNodes(); Vector & boundary = model->getBoundary(); Vector & force = model->getForce(); Vector & displacment = model->getDisplacement(); //initial conditions model->getForce().clear(); model->getDisplacement().clear(); model->getVelocity().clear(); model->getAcceleration().clear(); // MeshUtils::buildFacets(mesh); // MeshUtils::buildSurfaceID(mesh); // CSR surface_nodes; // MeshUtils::buildNodesPerSurface(mesh, surface_nodes); UInt node_to_print = -1; bool print_node = false; // for (UInt s = 0; s < surface_nodes.getNbRows(); ++s) { // CSR::iterator snode = surface_nodes.begin(s); // for(; snode != surface_nodes.end(s); ++snode) { // UInt n = *snode; Vector node_to_displace; for (UInt n = 0; n < mesh.getNbNodes(); ++n) { Real x = position(n, 0); Real y = position(n, 1); Real z = 0; if(spatial_dimension == 3) z = position(n, 2); if(Math::are_float_equal(x, 0.) && Math::are_float_equal(y, bar_height / 2.)) { boundary(n,0) = true; boundary(n,1) = true; if(spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.)) boundary(n,2) = true; } if(Math::are_float_equal(x, bar_length) && Math::are_float_equal(y, bar_height / 2.)) { boundary(n,1) = true; if(spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.)) boundary(n,2) = true; } if(Math::are_float_equal(x, bar_length / 2.) && Math::are_float_equal(y, bar_height / 2.)) { if(spatial_dimension < 3 || (spatial_dimension == 3 && Math::are_float_equal(z, bar_depth / 2.))) { force(n,1) = F; if(mesh.isLocalOrMasterNode(n)) { print_node = true; node_to_print = n; std::cout << "I, proc " << prank +1 << " handle the print of node " << n << "(" << x << ", "<< y << ", " << z << ")" << std::endl; } } } } // } model->setTimeStep(time_step); model->updateResidual(); std::stringstream out; out << "position-" << TYPE << "_" << std::scientific << time_step << ".csv"; DumperParaview dumper; paraviewInit(dumper, *model); std::ofstream pos; if(print_node) { pos.open(out.str().c_str()); if(!pos.good()) { std::cerr << "Cannot open file " << out.str() <assembleStiffnessMatrix(); model->assembleMass(); // model->assembleMassLumped(); // Vector lumped_mass(0,spatial_dimension); // model->getMassMatrix().lump(lumped_mass); // debug::setDebugLevel(dblTest); // std::cout << model->getMass() << lumped_mass; // debug::setDebugLevel(dblWarning); model->getMassMatrix().saveMatrix("M.mtx"); model->getStiffnessMatrix().saveMatrix("K.mtx"); /// time loop for (UInt s = 1; time < 0.62; ++s) { model->implicitPred(); /// convergence loop do { if(count > 0 && prank == 0) std::cout << "passing step " << s << " " << s * time_step << "s - " << std::setw(4) << count << " : " << std::scientific << error << "\r" << std::flush; model->updateResidual(); model->solveDynamic(); model->implicitCorr(); count++; } while(!model->testConvergenceIncrement(1e-12, error) && (count < 1000)); if(prank == 0) std::cout << "passing step " << s << " " << s * time_step << "s - " << std::setw(4) << count << " : " << std::scientific << error << std::endl; count = 0; // if(s % print_freq == 0) { // std::cout << "passing step " << s << "/" << max_steps << " " << s * time_step << "s - " << count / print_freq << std::endl; // count = 0; // } if(print_node) pos << s << "," << s * time_step << "," << displacment(node_to_print, 1) << "," << analytical_solution(s*time_step) << std::endl; #ifdef AKANTU_USE_IOHELPER if(s % 10 == 0) paraviewDump(dumper); #endif time += time_step; } if(print_node) pos.close(); delete model; finalize(); return EXIT_SUCCESS; } /* -------------------------------------------------------------------------- */ /* Dumper vars */ /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER /* -------------------------------------------------------------------------- */ template UInt paraviewType(); template <> UInt paraviewType<_segment_2>() { return LINE1; }; template <> UInt paraviewType<_segment_3>() { return LINE2; }; template <> UInt paraviewType<_triangle_3>() { return TRIANGLE1; }; template <> UInt paraviewType<_triangle_6>() { return TRIANGLE2; }; template <> UInt paraviewType<_quadrangle_4>() { return QUAD1; }; template <> UInt paraviewType<_tetrahedron_4>() { return TETRA1; }; template <> UInt paraviewType<_tetrahedron_10>() { return TETRA2; }; template <> UInt paraviewType<_hexahedron_8>() { return HEX1; }; /* -------------------------------------------------------------------------- */ void paraviewInit(Dumper & dumper, const SolidMechanicsModel & model) { UInt spatial_dimension = ElementClass::getSpatialDimension(); UInt nb_nodes = model.getFEM().getMesh().getNbNodes(); UInt nb_element = model.getFEM().getMesh().getNbElement(TYPE); std::stringstream filename; filename << "dynamic_implicit_beam_" << TYPE; dumper.SetMode(TEXT); dumper.SetParallelContext(StaticCommunicator::getStaticCommunicator()->whoAmI(), StaticCommunicator::getStaticCommunicator()->getNbProc()); dumper.SetPoints(model.getFEM().getMesh().getNodes().values, spatial_dimension, nb_nodes, filename.str().c_str()); dumper.SetConnectivity((int *)model.getFEM().getMesh().getConnectivity(TYPE).values, paraviewType(), nb_element, C_MODE); dumper.AddNodeDataField(model.getDisplacement().values, spatial_dimension, "displacements"); dumper.AddNodeDataField(model.getVelocity().values, spatial_dimension, "velocity"); dumper.AddNodeDataField(model.getAcceleration().values, spatial_dimension, "acceleration"); dumper.AddNodeDataField(model.getResidual().values, spatial_dimension, "residual"); dumper.AddNodeDataField(model.getForce().values, spatial_dimension, "applied_force"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "strain"); dumper.AddElemDataField(model.getMaterial(0).getStrain(TYPE).values, spatial_dimension*spatial_dimension, "stress"); dumper.SetEmbeddedValue("displacements", 1); dumper.SetEmbeddedValue("applied_force", 1); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); } /* -------------------------------------------------------------------------- */ void paraviewDump(Dumper & dumper) { dumper.Dump(); } /* -------------------------------------------------------------------------- */ #endif diff --git a/test/test_solver/test_sparse_matrix_assemble.cc b/test/test_solver/test_sparse_matrix_assemble.cc index d81199a00..3ebc68006 100644 --- a/test/test_solver/test_sparse_matrix_assemble.cc +++ b/test/test_solver/test_sparse_matrix_assemble.cc @@ -1,77 +1,78 @@ /** * @file test_sparse_matrix_assemble.cc * @author Nicolas Richart * @date Fri Nov 5 11:13:33 2010 * * @brief test the assembling method of the SparseMatrix class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::UInt spatial_dimension = 2; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::UInt nb_nodes = mesh.getNbNodes(); akantu::SparseMatrix sparse_matrix(nb_nodes * spatial_dimension, akantu::_symmetric, spatial_dimension); akantu::DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); + dof_synchronizer.initGlobalDOFEquationNumbers(); sparse_matrix.buildProfile(mesh, dof_synchronizer); // const akantu::Mesh::ConnectivityTypeList & type_list = mesh.getConnectivityTypeList(); // akantu::Mesh::ConnectivityTypeList::const_iterator it; // for(it = type_list.begin(); it != type_list.end(); ++it) { // if(mesh.getSpatialDimension(*it) != spatial_dimension) continue; // akantu::UInt nb_element = mesh.getNbElement(*it); // akantu::UInt nb_nodes_per_element = mesh.getNbNodesPerElement(*it); // akantu::Element element(*it); // akantu::UInt m = nb_nodes_per_element * spatial_dimension; // akantu::Vector local_mat(m, m, 1, "local_mat"); // for(akantu::UInt e = 0; e < nb_element; ++e) { // element.element = e; // sparse_matrix.addToMatrix(local_mat.values, element, nb_nodes_per_element); // } // } sparse_matrix.saveMatrix("matrix.mtx"); akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_solver/test_sparse_matrix_product.cc b/test/test_solver/test_sparse_matrix_product.cc index adccb9235..65f9493cf 100644 --- a/test/test_solver/test_sparse_matrix_product.cc +++ b/test/test_solver/test_sparse_matrix_product.cc @@ -1,144 +1,145 @@ /** * @file test_sparse_matrix_product.cc * @author Nicolas Richart * @date Mon Jun 6 15:06:47 2011 * * @brief test the matrix vector product in parallel * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io_msh.hh" #include "mesh_partition_scotch.hh" #include "distributed_synchronizer.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" /* -------------------------------------------------------------------------- */ using namespace akantu; /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(&argc, &argv); const UInt spatial_dimension = 2; const UInt nb_dof = 3; StaticCommunicator * comm = akantu::StaticCommunicator::getStaticCommunicator(); Int psize = comm->getNbProc(); Int prank = comm->whoAmI(); Mesh mesh(spatial_dimension); /* ------------------------------------------------------------------------ */ /* Parallel initialization */ /* ------------------------------------------------------------------------ */ DistributedSynchronizer * communicator; MeshPartition * partition; if(prank == 0) { MeshIOMSH mesh_io; mesh_io.read("bar.msh", mesh); std::cout << "Partitioning mesh..." << std::endl; partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } UInt nb_nodes = mesh.getNbNodes(); UInt nb_global_node = mesh.getNbGlobalNodes(); - Vector equation_number(nb_nodes, nb_dof); - for (UInt n = 0; n < nb_nodes; ++n) { - UInt real_n = mesh.getNodeGlobalId(n); - bool is_local_node = !(mesh.isPureGhostNode(n)); - for (UInt d = 0; d < nb_dof; ++d) { - UInt global_eq_num = (is_local_node ? real_n : nb_global_node + real_n) * nb_dof + d; - equation_number(n, d) = global_eq_num; - } - } + // Vector equation_number(nb_nodes, nb_dof); + // for (UInt n = 0; n < nb_nodes; ++n) { + // UInt real_n = mesh.getNodeGlobalId(n); + // bool is_local_node = !(mesh.isPureGhostNode(n)); + // for (UInt d = 0; d < nb_dof; ++d) { + // UInt global_eq_num = (is_local_node ? real_n : nb_global_node + real_n) * nb_dof + d; + // equation_number(n, d) = global_eq_num; + // } + // } if (prank == 0) std::cout << "Creating a SparseMatrix" << std::endl; SparseMatrix sparse_matrix(nb_global_node * nb_dof, _symmetric, nb_dof, "matrix"); DOFSynchronizer dof_synchronizer(mesh, nb_dof); + dof_synchronizer.initGlobalDOFEquationNumbers(); sparse_matrix.buildProfile(mesh, dof_synchronizer); Vector dof_vector(nb_nodes, nb_dof, "vector"); if (prank == 0) std::cout << "Filling the matrix" << std::endl; UInt nz = sparse_matrix.getNbNonZero(); const Vector & irn = sparse_matrix.getIRN(); const Vector & jcn = sparse_matrix.getJCN(); for (UInt i = 0; i < nz; ++i) { sparse_matrix.addToMatrix(irn(i) - 1, jcn(i) - 1, 1.); } std::stringstream str; str << "Matrix_" << prank << ".mtx"; sparse_matrix.saveMatrix(str.str()); for (UInt n = 0; n < nb_nodes; ++n) { for (UInt d = 0; d < nb_dof; ++d) { dof_vector(n,d) = 1.; } } if (prank == 0) std::cout << "Computing x = A * x" << std::endl; dof_vector *= sparse_matrix; if (prank == 0) std::cout << "Lumping the matrix" << std::endl; Vector lumped(0,nb_dof); sparse_matrix.lump(lumped); if (prank == 0) std::cout << "Gathering the results on proc 0" << std::endl; if(psize > 1) { const_cast(sparse_matrix.getDOFSynchronizer()).initScatterGatherCommunicationScheme(); if(prank == 0) { Vector gathered(0, nb_dof); Vector lump_gathered(0, nb_dof); sparse_matrix.getDOFSynchronizer().gather(dof_vector, 0, &gathered); sparse_matrix.getDOFSynchronizer().gather(lumped, 0, &lump_gathered); debug::setDebugLevel(dblTest); std::cout << gathered << std::endl; std::cout << lump_gathered << std::endl; debug::setDebugLevel(dblWarning); } else { sparse_matrix.getDOFSynchronizer().gather(dof_vector, 0); sparse_matrix.getDOFSynchronizer().gather(lumped, 0); } } else { debug::setDebugLevel(dblTest); std::cout << dof_vector << std::endl; std::cout << lumped << std::endl; debug::setDebugLevel(dblWarning); } finalize(); return 0; } diff --git a/test/test_solver/test_sparse_matrix_profile.cc b/test/test_solver/test_sparse_matrix_profile.cc index a8382d348..329fae166 100644 --- a/test/test_solver/test_sparse_matrix_profile.cc +++ b/test/test_solver/test_sparse_matrix_profile.cc @@ -1,94 +1,97 @@ /** * @file test_sparse_matrix_profile.cc * @author Nicolas Richart * @date Fri Nov 5 11:13:33 2010 * * @brief test the profile generation of the SparseMatrix class * * @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 . * */ /* -------------------------------------------------------------------------- */ #include /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "sparse_matrix.hh" #include "dof_synchronizer.hh" #ifdef AKANTU_USE_SCOTCH #include "mesh_partition_scotch.hh" #endif /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { akantu::initialize(&argc, &argv); akantu::UInt spatial_dimension = 2; akantu::Mesh mesh(spatial_dimension); akantu::MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); akantu::SparseMatrix sparse_matrix_hand(10, akantu::_symmetric, 1, "hand"); for(akantu::UInt i = 0; i < 10; ++i) { sparse_matrix_hand.addToProfile(i, i); } sparse_matrix_hand.addToProfile(0,9); for(akantu::UInt i = 0; i < 10; ++i) { sparse_matrix_hand.addToMatrix(i, i, i*10); } sparse_matrix_hand.addToMatrix(0,9, 100); sparse_matrix_hand.saveProfile("profile_hand.mtx"); sparse_matrix_hand.saveMatrix("matrix_hand.mtx"); /* ------------------------------------------------------------------------ */ akantu::UInt nb_nodes = mesh.getNbNodes(); akantu::SparseMatrix sparse_matrix(nb_nodes * spatial_dimension, akantu::_symmetric, spatial_dimension, "mesh"); akantu::DOFSynchronizer dof_synchronizer(mesh, spatial_dimension); + dof_synchronizer.initGlobalDOFEquationNumbers(); sparse_matrix.buildProfile(mesh, dof_synchronizer); sparse_matrix.saveProfile("profile.mtx"); /* ------------------------------------------------------------------------ */ #ifdef AKANTU_USE_SCOTCH mesh_io.write("triangle_breorder.msh", mesh); akantu::MeshPartition * partition = new akantu::MeshPartitionScotch(mesh, spatial_dimension); partition->reorder(); delete partition; akantu::DOFSynchronizer dof_synchronizer_re(mesh, spatial_dimension); + dof_synchronizer_re.initGlobalDOFEquationNumbers(); + sparse_matrix.buildProfile(mesh, dof_synchronizer_re); sparse_matrix.saveProfile("profile_reorder.mtx"); mesh_io.write("triangle_reorder.msh", mesh); #endif akantu::finalize(); return EXIT_SUCCESS; } diff --git a/test/test_surface_extraction/CMakeLists.txt b/test/test_surface_extraction/CMakeLists.txt index fe92d8ae4..e8f5aa0d8 100644 --- a/test/test_surface_extraction/CMakeLists.txt +++ b/test/test_surface_extraction/CMakeLists.txt @@ -1,38 +1,40 @@ #=============================================================================== # @file CMakeLists.txt # @author Leonardo Snozzi # @date Mon Oct 25 09:40:24 2010 # # @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 . # # @section DESCRIPTION # #=============================================================================== #=============================================================================== add_mesh(test_surface_extraction_2d_mesh squares.geo 2 1) register_test(test_surface_extraction_triangle_3 test_surface_extraction_triangle_3.cc) add_dependencies(test_surface_extraction_triangle_3 test_surface_extraction_2d_mesh) #=============================================================================== add_mesh(test_surface_extraction_3d_mesh cubes.geo 3 1) register_test(test_surface_extraction_tetrahedron_4 test_surface_extraction_tetrahedron_4.cc) -add_dependencies(test_surface_extraction_tetrahedron_4 test_surface_extraction_3d_mesh) \ No newline at end of file +add_dependencies(test_surface_extraction_tetrahedron_4 test_surface_extraction_3d_mesh) + +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/paraview) \ No newline at end of file diff --git a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc b/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc index 0be874a5d..b01970805 100644 --- a/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc +++ b/test/test_surface_extraction/test_surface_extraction_tetrahedron_4.cc @@ -1,87 +1,89 @@ /** * @file test_surface_extraction_3d.cc * @author Leonardo Snozzi * @date Mon Oct 25 11:40:12 2010 * * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 3; + akantu::initialize(&argc, &argv); + Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("cubes.msh", mesh); MeshUtils::buildFacets(mesh,1,0); MeshUtils::buildSurfaceID(mesh); unsigned int nb_nodes = mesh.getNbNodes(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_tetrahedron_4).values, TETRA1, mesh.getNbElement(_tetrahedron_4), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); dumper_surface.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction_boundary"); dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); - double * surf_id = new double [mesh.getSurfaceId(_triangle_3).getSize()]; - for (UInt i = 0; i < mesh.getSurfaceId(_triangle_3).getSize(); ++i) - surf_id[i] = (double)mesh.getSurfaceId(_triangle_3).values[i]; + double * surf_id = new double [mesh.getSurfaceID(_triangle_3).getSize()]; + for (UInt i = 0; i < mesh.getSurfaceID(_triangle_3).getSize(); ++i) + surf_id[i] = (double)mesh.getSurfaceID(_triangle_3).values[i]; dumper_surface.AddElemDataField(surf_id, 1, "surface_id"); - delete [] surf_id; dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); + delete [] surf_id; #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc b/test/test_surface_extraction/test_surface_extraction_triangle_3.cc index 538dfddf2..e04556eed 100644 --- a/test/test_surface_extraction/test_surface_extraction_triangle_3.cc +++ b/test/test_surface_extraction/test_surface_extraction_triangle_3.cc @@ -1,87 +1,89 @@ /** * @file test_surface_extraction_2d.cc * @author Leonardo Snozzi * @date Mon Oct 25 09:47:15 2010 * - * @brief + * @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 . * */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "mesh.hh" #include "mesh_io.hh" #include "mesh_io_msh.hh" #include "mesh_utils.hh" #include "solid_mechanics_model.hh" #include "material.hh" #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; int main(int argc, char *argv[]) { int dim = 2; + akantu::initialize(&argc, &argv); + Mesh mesh(dim); MeshIOMSH mesh_io; mesh_io.read("squares.msh", mesh); - - MeshUtils::buildFacets(mesh,1,0); + + MeshUtils::buildFacets(mesh, 1, 0); MeshUtils::buildSurfaceID(mesh); unsigned int nb_nodes = mesh.getNbNodes(); #ifdef AKANTU_USE_IOHELPER DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction"); dumper.SetConnectivity((int*)mesh.getConnectivity(_triangle_3).values, TRIANGLE1, mesh.getNbElement(_triangle_3), C_MODE); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); DumperParaview dumper_surface; dumper_surface.SetMode(TEXT); dumper_surface.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-surface-extraction_boundary"); - + dumper_surface.SetConnectivity((int *)mesh.getConnectivity(_segment_2).values, LINE1, mesh.getNbElement(_segment_2), C_MODE); - double * surf_id = new double [mesh.getSurfaceId(_segment_2).getSize()]; - for (UInt i = 0; i < mesh.getSurfaceId(_segment_2).getSize(); ++i) - surf_id[i] = (double)mesh.getSurfaceId(_segment_2).values[i]; + double * surf_id = new double [mesh.getSurfaceID(_segment_2).getSize()]; + for (UInt i = 0; i < mesh.getSurfaceID(_segment_2).getSize(); ++i) + surf_id[i] = (double)mesh.getSurfaceID(_segment_2).values[i]; dumper_surface.AddElemDataField(surf_id, 1, "surface_id"); - delete [] surf_id; dumper_surface.SetPrefix("paraview/"); dumper_surface.Init(); dumper_surface.Dump(); + delete [] surf_id; #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; } diff --git a/test/test_synchronizer/test_synchronizer_communication.cc b/test/test_synchronizer/test_synchronizer_communication.cc index 0ec38bcf7..4f7f6c0d1 100644 --- a/test/test_synchronizer/test_synchronizer_communication.cc +++ b/test/test_synchronizer/test_synchronizer_communication.cc @@ -1,278 +1,278 @@ /** * @file test_synchronizer_communication.cc * @author Nicolas Richart * @date Thu Aug 19 13:05:27 2010 * * @brief test to synchronize barycenters * * @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 . * */ /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #include "aka_common.hh" #include "static_communicator.hh" #include "distributed_synchronizer.hh" #include "synchronizer_registry.hh" #include "mesh.hh" #include "mesh_io_msh.hh" #include "mesh_partition_scotch.hh" #include "communication_buffer.hh" /* -------------------------------------------------------------------------- */ #ifdef AKANTU_USE_IOHELPER # include "io_helper.h" #endif //AKANTU_USE_IOHELPER using namespace akantu; class TestAccessor : public DataAccessor { /* ------------------------------------------------------------------------ */ /* Constructors/Destructors */ /* ------------------------------------------------------------------------ */ public: TestAccessor(const Mesh & mesh); ~TestAccessor(); - AKANTU_GET_MACRO_BY_ELEMENT_TYPE(GhostBarycenter, ghost_barycenter, const Vector); + AKANTU_GET_MACRO_BY_ELEMENT_TYPE_CONST(GhostBarycenter, ghost_barycenter, Real); /* ------------------------------------------------------------------------ */ /* Ghost Synchronizer inherited members */ /* ------------------------------------------------------------------------ */ protected: virtual UInt getNbDataToPack(const Element & element, SynchronizationTag tag) const; virtual UInt getNbDataToUnpack(const Element & element, SynchronizationTag tag) const; virtual void packData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; virtual void unpackData(CommunicationBuffer & buffer, const Element & element, SynchronizationTag tag) const; virtual UInt getNbDataToPack(SynchronizationTag tag) const; virtual UInt getNbDataToUnpack(SynchronizationTag tag) const; virtual void packData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; virtual void unpackData(CommunicationBuffer & buffer, const UInt index, SynchronizationTag tag) const; /* ------------------------------------------------------------------------ */ /* Class Members */ /* ------------------------------------------------------------------------ */ protected: std::string id; ByElementTypeReal ghost_barycenter; const Mesh & mesh; }; /* -------------------------------------------------------------------------- */ /* TestSynchronizer implementation */ /* -------------------------------------------------------------------------- */ TestAccessor::TestAccessor(const Mesh & mesh) : mesh(mesh) { UInt spatial_dimension = mesh.getSpatialDimension(); id = "test_synchronizer"; Mesh::ConnectivityTypeList::const_iterator it; const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; UInt nb_ghost_element = mesh.getNbElement(*it,_ghost); - ghost_barycenter[*it] = new Vector(nb_ghost_element, + ghost_barycenter(*it) = new Vector(nb_ghost_element, spatial_dimension, std::numeric_limits::quiet_NaN(), "ghost_barycenter"); } } TestAccessor::~TestAccessor() { UInt spatial_dimension = mesh.getSpatialDimension(); Mesh::ConnectivityTypeList::const_iterator it; const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != spatial_dimension) continue; - delete ghost_barycenter[*it]; + delete ghost_barycenter(*it); } } UInt TestAccessor::getNbDataToPack(const Element & element, __attribute__ ((unused)) SynchronizationTag tag) const { return Mesh::getSpatialDimension(element.type) * sizeof(Real); } UInt TestAccessor::getNbDataToUnpack(const Element & element, __attribute__ ((unused)) SynchronizationTag tag) const { return Mesh::getSpatialDimension(element.type) * sizeof(Real); } void TestAccessor::packData(CommunicationBuffer & buffer, const Element & element, __attribute__ ((unused)) SynchronizationTag tag) const { UInt spatial_dimension = Mesh::getSpatialDimension(element.type); types::RVector bary(spatial_dimension); mesh.getBarycenter(element.element, element.type, bary.storage()); buffer << bary; } void TestAccessor::unpackData(CommunicationBuffer & buffer, const Element & element, __attribute__ ((unused)) SynchronizationTag tag) const { UInt spatial_dimension = Mesh::getSpatialDimension(element.type); - Vector::iterator bary = ghost_barycenter[element.type]->begin(spatial_dimension); + Vector::iterator bary = ghost_barycenter(element.type)->begin(spatial_dimension); buffer >> bary[element.element]; } UInt TestAccessor::getNbDataToPack(__attribute__ ((unused)) SynchronizationTag tag) const { return 0; } UInt TestAccessor::getNbDataToUnpack(__attribute__ ((unused)) SynchronizationTag tag) const { return 0; } void TestAccessor::packData(__attribute__ ((unused)) CommunicationBuffer & buffer, __attribute__ ((unused)) const UInt index, __attribute__ ((unused)) SynchronizationTag tag) const { } void TestAccessor::unpackData(__attribute__ ((unused)) CommunicationBuffer & buffer, __attribute__ ((unused)) const UInt index, __attribute__ ((unused)) SynchronizationTag tag) const { } /* -------------------------------------------------------------------------- */ /* Main */ /* -------------------------------------------------------------------------- */ int main(int argc, char *argv[]) { initialize(&argc, &argv); int dim = 2; ElementType type = _triangle_3; Mesh mesh(dim); StaticCommunicator * comm = StaticCommunicator::getStaticCommunicator(); Int psize = comm->getNbProc(); Int prank = comm->whoAmI(); DistributedSynchronizer * communicator; if(prank == 0) { MeshIOMSH mesh_io; mesh_io.read("triangle.msh", mesh); MeshPartition * partition = new MeshPartitionScotch(mesh, dim); partition->partitionate(psize); communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, partition); delete partition; } else { communicator = DistributedSynchronizer::createDistributedSynchronizerMesh(mesh, NULL); } comm->barrier(); AKANTU_DEBUG_INFO("Creating TestAccessor"); TestAccessor test_accessor(mesh); SynchronizerRegistry synch_registry(test_accessor); synch_registry.registerSynchronizer(*communicator,_gst_test); AKANTU_DEBUG_INFO("Synchronizing tag"); synch_registry.synchronize(_gst_test); Mesh::ConnectivityTypeList::const_iterator it; const Mesh::ConnectivityTypeList & ghost_type_list = mesh.getConnectivityTypeList(_ghost); for(it = ghost_type_list.begin(); it != ghost_type_list.end(); ++it) { if(Mesh::getSpatialDimension(*it) != mesh.getSpatialDimension()) continue; UInt spatial_dimension = Mesh::getSpatialDimension(*it); UInt nb_ghost_element = mesh.getNbElement(*it,_ghost); for (UInt el = 0; el < nb_ghost_element; ++el) { Real barycenter[spatial_dimension]; mesh.getBarycenter(el, *it, barycenter, _ghost); for (UInt i = 0; i < spatial_dimension; ++i) { if(fabs(barycenter[i] - test_accessor.getGhostBarycenter(*it).values[el * spatial_dimension + i]) > std::numeric_limits::epsilon()) AKANTU_DEBUG_ERROR("The barycenter of ghost element " << el << " on proc " << prank << " does not match the one get during synchronisation" ); } } } #ifdef AKANTU_USE_IOHELPER unsigned int nb_nodes = mesh.getNbNodes(); unsigned int nb_element = mesh.getNbElement(type); DumperParaview dumper; dumper.SetMode(TEXT); dumper.SetParallelContext(prank, psize); dumper.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-scotch-partition"); dumper.SetConnectivity((int*) mesh.getConnectivity(type).values, TRIANGLE1, nb_element, C_MODE); double * part = new double[nb_element]; for (unsigned int i = 0; i < nb_element; ++i) part[i] = prank; dumper.AddElemDataField(part, 1, "partitions"); dumper.SetPrefix("paraview/"); dumper.Init(); dumper.Dump(); delete [] part; unsigned int nb_ghost_element = mesh.getNbElement(type,_ghost); DumperParaview dumper_ghost; dumper_ghost.SetMode(TEXT); dumper_ghost.SetParallelContext(prank, psize); dumper_ghost.SetPoints(mesh.getNodes().values, dim, nb_nodes, "test-scotch-partition_ghost"); dumper_ghost.SetConnectivity((int*) mesh.getConnectivity(type,_ghost).values, TRIANGLE1, nb_ghost_element, C_MODE); part = new double[nb_ghost_element]; for (unsigned int i = 0; i < nb_ghost_element; ++i) part[i] = prank; dumper_ghost.AddElemDataField(part, 1, "partitions"); dumper_ghost.SetPrefix("paraview/"); dumper_ghost.Init(); dumper_ghost.Dump(); delete [] part; #endif //AKANTU_USE_IOHELPER finalize(); return EXIT_SUCCESS; }